Java高级特性之内部类
所谓内部类(Inner Class),就是将一个类定义在另一个类的内部。内部的类称之为内部类。
内部类的主要特点
内部类可以很好的实现隐藏,可以使用protected、private修饰符。
内部类可以直接访问外部类的所有成员,包括私有的成员。
外部类不能直接访问内部类的成员,必须首先要建立内部类的对象才可访问。
内部类可以解决一些问题,比如间接地去实现多继承。可以避免修改接口而实现同一个类中两种同名方法的调用。
成员内部类
成员内部类特点
成员内部类属于外部类的实例成员,成员内部类可以有public/private/default/protected权限修饰符。在成员内部类中访问外部的成员方法和属性,要使用“外部类名.this.成员方法”和“外部类名.this.成员属性”的形式
创建成员内部类的实例使用“外部类名.内部类名 实例名 = 外部类实例名.new 内部类名()”的形式
成员内部类有以下限制
成员内部类不能与外部类重名
不能在成员内部类定义static属性、方法和类(static final形式的常量定义除外)。因为一个成员内部类实例必然与一个外部类实例关联,static成员完全可以移到外部类中去
demo:
public class MemberInnerClassDemo { public static void main(String[]args) { //创建外部类对象 Outer1 outer1=new Outer1(); //创建内部类对象 Outer1.Inner1 inner1=outer1.new Inner1(); inner1.innerShow(); } } class Outer1{ private String name="张三"; private int num1=10; public void outerShow(){ System.out.println("姓名:"+name+",编号:"+num1); } //内部类,当内部类声明为private时,只能在对应的外部类中使用,不能在其他类中使用 public class Inner1{ private String name="李四"; private int num1=12; //private static int num2=30;//报错:内部类Outer1.Inner1中的静态声明非法 private static final int num3=50;//常量可以 public void innerShow(){ System.out.println("内部类 姓名:"+name+",编号:"+num1); //同名时,用Outer1.this区分 System.out.println("外部类姓名:"+Outer1.this.name); outerShow();//直接访问外部类的属性和方法 } } }
效果:
使用内部类间接实现多继承
由于一个类只能直接继承自一个父类,通过多个内部类分别继承自一个类,就可以间接实现多继承
demo:
public class MultiExtendsDemo { public static void main(String[]args) { //创建外部类对象 C c=new C(); c.showA(); c.showB(); } } class A{ public void showA(){ System.out.println("A"); } } class B{ public void showB(){ System.out.println("B"); } } class C{ private class A1 extends A{ public void showA(){ super.showA(); } } private class B1 extends B{ public void showB(){ super.showB(); } } public void showA(){ new A1().showA(); } public void showB(){ new B1().showB(); } }
效果:
使用内部类间接实现父类与接口同名方法的重写与实现
使用内部类去实现接口方法,从而使得接口方法与父类抽象方法不冲突。
但这种方法没太大意义,当父类与接口方法重名时,理应改其中一个的方法名。这里只是说了一种思维方式能够处理重名问题。
demo:
public class SameFunctionDemo { public static void main(String[]args) { //创建外部类对象 Son son=new Son(); son.show(); son.show2(); } } abstract class Parent{ public abstract void show(); } interface IShow{ void show(); } class Son extends Parent{ public void show(){ System.out.println("抽象类中的show()"); } private class Inner2 implements IShow{ public void show(){ System.out.println("接口中的show()"); } } public void show2(){ new Inner2().show(); } }
效果:
Java高级特性之内部类
静态内部类及应用
静态内部类特点
使用static修饰的成员内部类叫静态内部类。
静态内部类跟外部类没有任何关系,只是在生成类定义时有影响。静态内部类可以看做是与外部类平级的类。使用方式与外部类平级的类完全相同
创建静态内部类的实例使用“外部类名.内部类名 实例名 = new 外部类名.内部类名()”
静态内部类有以下限制
静态内部类不能与外部类重名
静态内部类不能访问外部类的非静态和属性和方法、外部类不能访问内部类的非静态的属性和方法。
demo:
public class StaticInnerClassDemo { public static void main(String[]args) { //创建静态内部类对象 Outer2.Inner2 inner2=new Outer2.Inner2(); inner2.innerShow(); Outer2 outer2=new Outer2(); outer2.outerShow(); } } class Outer2{ private String name="张三"; private int num1=10; private static int num2=5; public void outerShow(){ System.out.println("姓名:"+name+",编号:"+num1); System.out.println(Inner2.num3);//外部类访问内部类的静态成员 } //static内部类与外部类平级,跟外部类没有任何关系 public static class Inner2{ private String name="李四"; private int num1=12; private static int num3=50;//常量 public void innerShow(){ System.out.println("内部类 姓名:"+name+",编号:"+num1); //System.out.println(Outer2.this.num1);//错误: 无法从静态上下文中引用非静态 变量 this System.out.println(Outer2.num2);//内部类访问外部类的静态成员 } } }
效果:
Java高级特性之内部类
匿名内部类及应用
匿名内部类特点
匿名内部类是没有名称的内部类,没办法引用它们。必须在创建时作为new语句的一部分来声明并创建它们的实例。
匿名内部类必须继承一个类(抽象的、非抽象的都行)或者实现一个接口。如果父类(或者接口)是抽象类,则匿名内部类必须实现其所有抽象方法
匿名内部类中可以定义代码块,用于实例的初始化,但不能定义静态代码块。
匿名内部类语法
new interface/superclass(){//类体} 这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例
demo:
public class AnonymousInnerClassDemo { public static void main(String[]args) { Person p=new Person(); //传统写法 //Animal dog=new Dog(); //p.feed(dog); //创建匿名内部类对象 IAnimal dog = new IAnimal(){//匿名对象,实现接口 public void eat(){//匿名内部类实现抽象方法 System.out.println("dog 啃骨头"); } }; p.feed(dog); Animal cat = new Animal(){//匿名对象,继承抽象类 private String name="lili"; public void eat(){//匿名内部类实现抽象方法 System.out.println("cat 吃鱼"); } public void show(){//匿名内部类可以实现自己的方法,但是引用变量为父类或接口,不能实际调用 System.out.println("我是 cat "+name); } }; p.feed(cat); //cat.show();//父类引用变量不能调用子类特有的成员 } } class Person{ public void feed(Animal animal){ System.out.print("人喂动物 "); animal.eat(); } public void feed(IAnimal animal){ System.out.print("人喂动物 "); animal.eat(); } } abstract class Animal{ public abstract void eat(); } interface IAnimal{ public abstract void eat(); } /*class Dog extends Animal{ public void eat(){ System.out.println("dog 啃骨头"); } } */
效果:
Java高级特性之内部类
局部内部类及应用(很少使用)
局部内部类特点
定义在代码块、方法体内的类叫局部内部类。
局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”和“外部类名.this.方法名()”的形式。
对外部世界完全隐藏,只能在其作用域内生成对象。
局部内部类有以下限制
局部内部类不能加访问修饰符,因为它们不是类成员。
局部内部类不能与外部类重名。
局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰。
demo:
public class LocalInnerClassDemo { public static void main(String[]args) { Outer3 outer=new Outer3(); outer.showOuter(); } } class Outer3{ private String name="张三"; private int num1=10; private static int num2=20; public void showOuter(){ int num4 = 50; final int num5 = 80; //局部内部类不能加访问修饰符 class Inner3{ private int num3=30; private int num1=100; public void showInner(){ System.out.println(num3); System.out.println("外部类成员变量name:"+Outer3.this.name); System.out.println("外部类成员变量num1:"+Outer3.this.num1); System.out.println("外部类静态变量num2:"+Outer3.num2); //报错:num4需要被声明为最终类型 //System.out.println("作用域内的局部变量num4:"+num4); System.out.println("作用域内的局部常量num5:"+num5); } } Inner3 inner=new Inner3(); inner.showInner(); } }
效果: