java内部类
一、内部类定义
1 public class Outer { 2 public static void main(String[] args) { 3 Outer outer = new Outer(); 4 //第一种方式创建内部类 5 Outer.Inner inner = outer.new Inner(); 6 //第二种方式创建内部类 7 inner = outer.getInner(); 8 inner.print(" "); 9 } 10 11 // 个人推荐使用第二种来获取成员内部类,尤其是该内部类的构造函数无参数时 12 public Inner getInner() { 13 return new Inner(); 14 } 15 16 public class Inner { 17 public void print(String str) { 18 System.out.println(str); 19 } 20 } 21 }
1 class Out { 2 private int age = 12; 3 4 class In { 5 private int age = 13; 6 public void print() { 7 int age = 14; 8 System.out.println("局部变量:" + age); 9 System.out.println("内部类变量:" + this.age); 10 System.out.println("外部类变量:" + Out.this.age); 11 } 12 } 13 } 14 15 public class Demo { 16 public static void main(String[] args) { 17 Out.In in = new Out().new In(); 18 in.print(); 19 } 20 }
运行结果:
局部变量:14
内部类变量:13
外部类变量:12
2. 局部内部类
1.方法定义局部内部类同方法定义局部变量一样,不能使用private、protected、public等访问修饰说明符修饰,也不能使用static修饰,但可以使用final和 abstract修饰
2.方法中的内部类可以访问外部类成员。对于方法的参数和局部变量,必须有final修饰才可以访问。
3.static方法中定义的内部类可以访问外部类定义的static成员
1 public class Parcel4 { 2 public Destination destination(String s) { 3 class PDestination implements Destination { 4 private String label; 5 6 private PDestination(String whereTo) { 7 label = whereTo; 8 } 9 10 public String readLabel() { 11 return label; 12 } 13 } 14 return new PDestination(s); 15 } 16 17 public static void main(String[] args) { 18 Parcel4 p = new Parcel4(); 19 Destination d = p.destination("Tasmania"); 20 } 21 }
1 public class Parcel5 { 2 private void internalTracking(boolean b) { 3 if (b) { 4 class TrackingSlip { 5 private String id; 6 TrackingSlip(String s) { 7 id = s; 8 } 9 String getSlip() { 10 return id; 11 } 12 } 13 TrackingSlip ts = new TrackingSlip("slip"); 14 String s = ts.getSlip(); 15 } 16 } 17 18 public void track() { 19 internalTracking(true); 20 } 21 22 public static void main(String[] args) { 23 Parcel5 p = new Parcel5(); 24 p.track(); 25
3.匿名内部类
定义类的最终目的是创建一个类的实例,但是如果某个类的实例只是用一次,则可以将类的定义与类的创建,放到与一起完成,或者说在定义类的同时就创建一个类。
声明和构造匿名内部类的一般格式如下:
1 new ClassOrInterfaceName(){ 3 /*类体*/ 5 }
1.匿名内部类可以继承一个类或实现一个接口,这里的ClassOrInterfaceName是匿名内部类所继承的类名或实现的接口名。但匿名内部类不能同时实现一个接口和继承一个类,也不能实现多个接口。如果实现了一个接口,该类是Object类的直接子类,匿名类继承一个类或实现一个接口,不需要extends和implements关键字。
2.由于匿名内部类没有名称,所以类体中不能定义构造方法,由于不知道类名也不能使用关键字来创建该类的实例。实际上匿名内部类的定义、构造、和第一次使用都发生在同样一个地方。此外,上式是一个表达式,返回的是一个对象的引用,所以可以直接使用或将其复制给一个对象变量。
1 public class Outer { 2 public static void main(String[] args) { 3 Outer outer = new Outer(); 4 Inner inner = outer.getInner("Inner", "gz"); 5 System.out.println(inner.getName()); 6 } 7 8 public Inner getInner(final String name, String city) { 9 return new Inner() { 10 private String nameStr = name; 11 12 public String getName() { 13 return nameStr; 14 } 15 }; 16 } 17 } 18 19 //注释后,编译时提示类Inner找不到 20 /* interface Inner { 21 String getName(); 22 } */
当所在的方法的形参需要被内部类里面使用时,该形参必须为final。
为什么要定义为final呢?
首先,内部类被编译的时候会生成一个单独的内部类的.class文件,这个文件并不与外部类在同一class文件中。
1 public void dosome(final String a,final int b){ 2 class Dosome{ 3 public void dosome(){ 4 System.out.println(a+b) 5 } 6 }; 7 Dosome some=new Dosome(); 8 some.dosome(); 9 }
从代码来看好像是那个内部类直接调用的a参数和b参数,但是实际上不是,在java编译器编译以后实际的操作代码是
class Outer$Dosome{ public Dosome(final String a,final int b){ this.Dosome$a=a; this.Dosome$b=b; } public void dosome(){ System.out.println(this.Dosome$a+this.Dosome$b); } } }
1 public class Outer { 2 public static void main(String[] args) { 3 Outer outer = new Outer(); 4 Inner inner = outer.getInner("Inner", "gz"); 5 System.out.println(inner.getName()); 6 System.out.println(inner.getProvince()); 7 } 8 9 public Inner getInner(final String name, final String city) { 10 return new Inner() { 11 private String nameStr = name; 12 private String province; 13 14 // 实例初始化 15 { 16 if (city.equals("gz")) { 17 province = "gd"; 18 }else { 19 province = ""; 20 } 21 } 22 23 public String getName() { 24 return nameStr; 25 } 26 27 public String getProvince() { 28 return province; 29 } 30 }; 31 } 32 } 33 34 interface Inner { 35 String getName(); 36 String getProvince(); 37 }
4.静态内部类
与类的其他成员相似,可以用static修饰内部类,这样的类称为静态内部类。静态内部类与静态内部方法相似,只能访问外部类的static成员,不能直接访问外部类的实例变量,与实例方法,只有通过对象引用才能访问。由于static内部类不具有任何对外部类实例的引用,因此static内部类中不能使用this关键字来访问外部类中的实例成员,但是可以访问外部类中的static成员。这与一般类的static方法想通。
1 public class MyOuter { 2 public static int x=100; 3 public static class MyInner{ 4 private String y="Hello!"; 5 public void innerMethod(){ 6 System.out.println("x="+x); 7 System.out.println("y="+y); 8 } 9 } 10 /** 11 * @param args 12 */ 13 public static void main(String[] args) { 14 MyOuter.MyInner si=new MyOuter.MyInner();//静态内部类不通过外部实例就可以创建对象;与类变量可以通过类名访问相似 15 si.innerMethod(); 16 // TODO Auto-generated method stub 17 } 18 }
运行结果:
x=100
y=Hello!

浙公网安备 33010602011771号