一、什麼是內部類?
內部類就是將一個類定義在另一個類中。
class Outer{
//內部類
class Inner{
}
}
二、內部類的分類
內部類分爲兩類:成員內部類(靜態和非靜態)和局部內部類(方法內,代碼塊內,構造器內)
class Outer {
//靜態成員內部類
static class StaticInner {
}
//非靜態內部類
class Inner {
}
//方法
public void method() {
//局部內部類
class MethodInner {
}
}
//非靜態代碼塊
{
//局部內部類
class BlockInner {
}
}
//靜態代碼塊
static{
//局部內部類
class BlockInner {
}
}
//構造器
public Outer() {
//局部內部類
class ConstructorInner {
}
}
}
2.1 成員內部類
成員內部類作爲外部類的成員,那麼可以調用外部類的結構,可以被static修飾,
可以被4種不同的權限修飾符修飾。
作爲一個類,那麼它必然有着作爲類的一切可以做的,包括了類內可以定義的各種東西(屬性,方法,構造器等,對於可以被static修飾的屬性,方法,只能當成員內部類被static修飾時纔有效),可以被final修飾,可以被abstract修飾。
class Outer {
private String outerName;
static int outerAge;
public void outerMethod(){
}
class Inner {
String name;
final int age=1;
//static int id=1; //Inner classes cannot have static declarations
public Inner(String name) {
this.name = name;
}
public void method(){
Outer.this.outerMethod();
//等價於
outerMethod();//相當於省略了Outer.this.
Outer.this.outerName="Inner";//可以省略了Outer.this.
Outer.outerAge=10;
System.out.println("我是方法");
}
public final void finalMethod(){
System.out.println("我是final方法");
}
//Inner classes cannot have static declarations
//public static void staticMethod(){
//}
}
private class InnerPrivate {
}
public class InnerPublic {
}
protected class InnerProtected {
}
final class InnerFinal {
}
static class StaticInner {
String name;
static String country="china";
final int ID=10;
public StaticInner(String name) {
this.name = name;
}
public void method(){
System.out.println("我是方法");
}
public static void staticMethod(){
System.out.println("我是靜態方法");
}
public final void finalMethod(){
System.out.println("我是final方法");
}
}
}
在類中調用本類中的屬性和方法通過this調用,那麼在內部類中如何調用外部類中的屬性和方法呢?在上例中,Outer.this.outerName="Inner";
和Outer.this.outerMethod()
的形式來調用外部類中的屬性和方法,即外部類名.this.屬性或外部類名.this.方法,外部類名.this所代表的含義就是外部類對象的引用。當前外部類屬性和內部類屬性並不重名,那麼如果重名該如何區分呢?
class Outer{
String name="outer";
class Inner{
String name="inner";
public void method(String name){
System.out.println(name);//形參
System.out.println(this.name);//Inner的name屬性
System.out.println(Outer.this.name);//Outer的name屬性
}
}
}
public class Demo{
public static void main(String[] args) {
Outer.Inner inner=new Outer().new Inner();
inner.method("method");
}
}
輸出:
method
inner
outer
public class Demo {
public static void main(String[] args) {
Outer outer=new Outer();
Outer.Inner inner = outer.new Inner("hh");
inner.method();
System.out.println("=======================================");
Outer.StaticInner staticInner=new Outer.StaticInner("hh");
staticInner.method();
}
}
輸出:
我是方法
=======================================
我是方法
上例中,對於非靜態內部類,我們通過使用外部類的對象來創建內部類的對象(如:outer.new Inner("hh");
,)來進行實例化內部類。爲什麼要如此?
在擁有外部類對象之前是不可能創建內部類對象的。這是因爲內部類對象會暗暗地連接到建它的外部類對象上。
上述來自《Java編程思想》
對於靜態內部類,我們則不需要外部類的對象了。直接通過new 外部類名.靜態內部類名的方式(如:new Outer.StaticInner("hh");
)
2.2 局部內部類
在上面我們知道了,局部內部類可以定義在代碼塊,構造器,方法中。
使用局部內部類,不能被public,private,protected修斯。使用局部內部類可以將自身對外部完全的隱藏起來。除了它所在的方法,不能通過任何辦法知道它的存在。局部內部類不僅能訪問外部類結構,還能訪問自身所在方法的局部變量。
class Outer{
String name="Outer";
public Comparable getComparable(String name){
class MyComparable implements Comparable{
@Override
public int compareTo(Object o) {
System.out.println("外部類name:"+Outer.this.name+",內部類name:"+name);
return 0;
}
}
return new MyComparable();
}
public Comparable getComparable2(final String name){
return new Comparable() {
@Override
public int compareTo(Object o) {
System.out.println("外部類name:"+Outer.this.name+",內部類name:"+name);
info();
return 0;
}
};
}
public void info(){
System.out.println("info");
}
}
public class Demo{
public static void main(String[] args) {
Outer outer=new Outer();
Comparable comparable = outer.getComparable("Inner");
comparable.compareTo(1);
System.out.println("==================================");
Comparable hh = outer.getComparable2("inner");
hh.compareTo(1);
}
}
輸出:
外部類name:Outer,內部類name:Inner
==================================
外部類name:Outer,內部類name:inner
info