一个类的内部又完整的嵌套了另一个类结构。被嵌套的类称为内部类,嵌套内部类的类称为外部类,是我们类的第五大成员(五大成员:属性、方法、构造器、代码块、内部类)内部类的最大特点就是可以直接访问私有属性,并且可以体现类与类之间的包含关系。
class Outer{ // 外部类 class Inner{ // 内部类 } } class Other{ // 外部其它类 }内部类的分类
1. 定义在外部类的局部位置上(方法/代码块内):A. 局部内部类(有类名) B. 匿名内部类(没有类名,重点)
2. 定义在外部类的成员位置上:A. 成员内部类(没用static修饰)B. 静态内部类(使用static修饰)
局部内部类1. 可以直接访问外部类的所有成员,包括私有的。
2. 不能添加访问修饰符,因为它相当于一个局部变量,局部变量是不能使用修饰符的,但是可以使用final修饰,因为局部变量也可以使用final。
3. 作用域:仅仅在定义它的方法或代码块中。
4. 外部类 访问 局部内部类的成员:创建对象再访问(必须在作用域内)。
5. 局部内部类 访问 外部类成员:直接访问。
public class Outer { private int n1 = 10; public void say(){ int n3 = 30; class Inner01{ int n2 = n1; //直接访问外部类成员 public void show(){ System.out.println("调用局部内部类的方法"); } } Inner01 a = new Inner01(); a.show(); //先创建对象再访问局部内部类的成员 } Inner01 b = new Inner01(); //报错,已经不在局部内部类的作用域中了 }
6. 外部其它类不能访问 局部内部类(因为 局部内部类相当于一个局部变量)。
7. 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用 外部类名.this.成员 去访问,其中 外部类名.this 相当于外部类。
public class Outer { private int n1 = 10; private static String name = "张三"; public void say(){ int n1 = 30; class Inner01{ int n1 = 1000; public void show(){ System.out.println(n1); //输出 1000,就近原则 System.out.println(this.n1); //输出 1000,用this还是就近原则 System.out.println(Outer.this.n1); //输出 10,外部类定义的变量 System.out.println(Outer.n1); //报错 } } Inner01 a = new Inner01(); a.show(); } } class Others{ Inner01 a = new Inner01(); //报错,外部其他类 不能访问 局部内部类 }匿名内部类
定义在外部类的局部位置,并且没有类名。(1)本质是类 (2)该类没有名字 (3)同时还是一个对象。
接口:
new 类或接口(参数列表){ //构造器 类体 }; //注意返回一个指向该类或接口的实例
public class Outer { public void create(){ //写在方法内 IA tiger = new IA(){ @Override public void say() { System.out.println("老虎嗷嗷叫"); } }; //匿名内部类,tiger的编译类型为IA,tiger的运行类型就是匿名内部类(也就是 Outer) } } interface IA{ void say(); }
实际上Jdk底层会给 匿名内部类 分配一个类名,分配的方法为 外部类类名+$(可用tiger的getClass方法查看),然后立即创建一个 Outer$1实例,并且把地址赋给 tiger。
class Outer implements IA { @override public void cry(){ System.out.println("老虎嗷嗷叫"); } }
类:
public class Outer { public void create(){ Person1 a = new Person1("Jack") { @Override public void say() { System.out.println("在匿名内部类重写父类方法"); } public void hello(){ System.out.println("调用匿名内部类独有的方法"); } //无法调用,因为编译类型为Person1,不能调用子类独有的方法 }; //匿名内部类,不加大括号就是正常的创建类,运行类型为Person1,而加了就是匿名内部类 a.say(); System.out.println(a.getClass()); //输出a的运行类型,为 Outer } } class Person1 { private String name; public Person1(String name) { this.name = name; } public void say(){ } }注意事项
1. 匿名内部类既是一个类的定义,同时它本身也是一个对象(本身就是个返回对象)。因此从语法上看,它既有定义类的特征,也有创建对象的特征,因此可以直接调用匿名内部类方法。
new Person1("Jack") { @Override public void say() { System.out.println("在匿名内部类重写父类方法"); } }.say(); //可以new之后直接调用
3. 可以直接访问外部类的所有成员,包含私有的。
4. 不能添加访问修饰符,因为它的地位就是一个局部变量。
5. 作用域:仅仅在定义它的方法或代码块中。
6. 匿名内部类 访问 外部类成员:直接访问。
7. 外部其它类 不能访问 匿名内部类(因为匿名内部类建立之后就销毁了)。
8. 如果外部类和内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想访问外部类的成员,则可以使用 外部类名.this.成员 去访问。
实例当作实参直接传递,简洁高效。
public class Outer{ public static void f1(IL il){ il.show(); } public static void main(String[] args) { f1(new IL() { // 把匿名内部类当作参数导入 @Override public void show() { System.out.println("导入匿名内部类"); } }); } } interface IL{ void show(); }
对比一下传统方法
public class Outer{ public static void f1(IL il){ il.show(); } public static void main(String[] args) { Picture a = new Picture(); // 创建一个对象 f1(a); // 利用接口的多态 } } interface IL{ void show(); } class Picture implements IL{ // 定义一个类实现接口 @Override public void show() { System.out.println("传统方法"); } }成员内部类
成员内部类定义在外部类的成员位置,并且没有static修饰。
1. 可以直接访问外部类的所有成员包含私有的。
2. 可以添加任意访问修饰符,因为它的地位就是一个成员。
3. 作用域:和外部类的其他成员一样,为整个类。
4. 成员内部类 访问 外部类成员:直接访问。
5. 外部类 访问 成员内部类:创建对象再访问。
class Outer{ private int n1 = 10; class inner{ public void show(){ System.out.println(n1); //内部成员类 调用 外部类(私有也可以访问) } } public void say(){ inner a = new inner(); // 先创建对象 a.show(); // 外部类 调用 内部成员类 } }
6. 外部其它类 访问 成员内部类
第一种方式:把 Inner01 看作 Outer01 的成员,Outer01.Inner01 为编译类型,用外部类实例new
class Others{ Outer01 outer = new Outer01(); Outer01.Inner01 inner = outer.new Inner01(); //相当于把 Inner01当作 Outer01的成员 }
第二种方式:在外部类中编写一个方法,可以返回 Inner01 对象
public Inner01 getInner01(){ Inner01 a = new Inner01(); return a; } //编写方法 class Others{ Outer01 outer01 = new Outer01(); Outer01.Inner01 inner01 = outer01.getInner01(); //用对象实例调用方法 }
7. 如果外部类和内部类的成员重名时,内部类访问遵循就近原则,如果想访问外部类的成员,则可以使用 外部类名.this.成员 去访问。
静态内部类静态内部类定义在外部类的成员位置,并且有static修饰。
1. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员。
2. 可以添加任意访问修饰符,因为它的地位就是一个成员。
3. 作用域:同其他的成员,为整个类体。
4. 静态内部类 访问 外部类:直接访问所有静态成员。
5. 外部类 访问 静态内部类:先在外部类中创建对象再访问。
6. 外部其它类 访问 静态内部类:
第一种方法:因为是静态内部类,可以通过类名直接访问(满足访问权限)。
Outer01.Inner01 inner01 = new Outer01.Inner01(); //直接用类名new
第二种方法:编写一个方法,可以返回静态内部类的对象实例。
public Inner01 create(){ return new Inner01(); //返回一个 静态内部类的实例 } class Others{ Outer01 a = new Outer01(); Outer01.Inner01 inner01 = a.create(); //调用方法返回实例 }
7. 如果外部类和内部类的成员重名时,内部类访问遵循就近原则,如果想访问外部类的成员,则可以使用 外部类名.成员 去访问(因为 外部类名.this 是对象名,而静态变量可以用类名访问)。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)