------- android培训、java培训、期待与您交流! ----------
如果把一个内部类放在方法里定义,则这个内部类就是一个局部内部类,局部内部类仅在该方法里有效。由于局部内部类不能在外部类的方法以外的地方使用,因此局部内部类也不能使用访问控制符和static修饰符修饰。
对于局部成员而言,不管是局部变量还是局部内部类,它们的上一级程序单元都是方法,而不是类,使用static修饰它们没有任何意义。因此,所有的局部成员都不能使用static修饰。不仅如此,因为局部成员的作用域是所在方法,其他程序单元永远也不可能访问另一个方法中的局部成员,所以所有的局部成员都不能使用访问控制符修饰。
如果需要用局部北部了定义变量,创建实例或派生子类,那么都只能在局部内部类所在的方法内进行。
1 public class LocalInnerClass 2 { 3 4 public static void main(String[] args) 5 { 6 //定义局部内部类 7 class InnerBase 8 { 9 int a; 10 } 11 //定义局部内部类的子类 12 class InnerSub extends InnerBase 13 { 14 int b; 15 } 16 //创建局部内部类的对象 17 InnerSub is = new InnerSub(); 18 is.a = 5; 19 is.b = 8; 20 System.out.println("InnerSub对象的a和b实例变量是:" + is.a + "," + is.b); 21 22 } 23 24 }
java8改进的匿名内部类
匿名内部类适合创建那种中需要一次使用的类,匿名内部类的语法有点奇怪,创建匿名内部类时会立即创建一个该类的实例,这个类定义立即消失,匿名内部类不能重复使用,
定义匿名内部类的格式如下:
new 实现接口() | 父类构造器(实参列表) { //匿名内部类的类体部分 }
可以看出,匿名内部类必须继承一个父类,或实现一个接口但最多只能继承一个父类,或实现一个接口。
关于匿名内部类还有如下两条规则:
1:匿名内部类不能是抽象类,因为系统在创建匿名内部类时,会立即创建匿名内部类的对象。因此不允许将匿名内部类定义成抽象类。
2:匿名内部类不能定义构造器。由于匿名内部类没有类名,所以无法定义构造器,但匿名内部类可以定义初始化块,可以通过实例初始化块来完成构造器需要完成的事。
最常用的创建匿名内部类的方式是需要创建某个接口类型的对象,如下程序所示:
1 interface Product 2 { 3 public double getPrice(); 4 public String getName(); 5 } 6 public class AnonymousTest 7 { 8 public void test(Product p) 9 { 10 System.out.println("购买了一个" + p.getName() + ", 花掉了" + p.getPrice()); 11 } 12 13 public static void main(String[] args) 14 { 15 AnonymousTest ta = new AnonymousTest(); 16 //调用test()时,需要传入一个Product参数 17 //此处传入匿名实现类的实例 18 ta.test(new Product() 19 { 20 21 @Override 22 public double getPrice() 23 { 24 return 567.8; 25 } 26 27 @Override 28 public String getName() 29 { 30 return "AGP显卡"; 31 } 32 }); 33 } 34 }
test()方法需要一个Product对象作为参数,但Product知识一个接口,无法直接创建对象,因此此处考虑创建一个Product接口实现类的对象传入该方法---如果这个Product接口实现类需要重复使用,则应该将该实现类定义成一个独立类;如果这个Product接口实现类只需使用一次,则可采用上面程序中的方式,定义一个匿名内部类。
定义匿名内部类无须class关键字,而是在定义匿名内部类时直接生成该匿名内部类的对象。
由于匿名内部类不能是抽象类,所以匿名内部类必须实现它的抽象父类或者接口里包含的所有抽象方法。
对于上面创建Product实现类对象的代码,可以拆分成如下代码。
1 public class AnonymousTest implements Product 2 { 3 4 @Override 5 public double getPrice() 6 { 7 return 567.8; 8 } 9 10 @Override 11 public String getName() 12 { 13 return "AGP显卡"; 14 } 15 16 public void test(Product p) 17 { 18 System.out.println("购买了一个" + p.getName() + ", 花掉了" + p.getPrice()); 19 } 20 21 public static void main(String[] args) 22 { 23 AnonymousTest ta = new AnonymousTest(); 24 //调用test()时,需要传入一个Product参数 25 ta.test(new AnonymousTest()); 26 } 27 }
当通过实现接口来创建匿名内部类时,匿名内部类也不能显式创建构造器,因此匿名内部类只有一个隐式的无参数构造器,故new接口名后的扩号里不能传入参数值。
但如果通过继承父类来创建匿名内部类时,匿名内部类将拥有和父类相似的构造器,此处的相似指的是拥有相同的参数列表。
1 abstract class Device 2 { 3 private String name; 4 public abstract double getPrice(); 5 public Device(){} 6 public Device(String name) 7 { 8 this.name = name; 9 } 10 11 public String getName() { 12 return name; 13 } 14 public void setName(String name) { 15 this.name = name; 16 } 17 18 } 19 public class AnonymousInner 20 { 21 public void test(Device d) 22 { 23 System.out.println("购买了一个" + d.getName() + ", 花掉了" + d.getPrice()); 24 } 25 public static void main(String[] args) 26 { 27 AnonymousInner ai = new AnonymousInner(); 28 // 调用有参数的构造器创建Device匿名实现类的对象 29 ai.test(new Device("电饭煲") 30 { 31 @Override 32 public double getPrice() 33 { 34 return 67.8; 35 } 36 }); 37 38 // 调用无参数的构造器创建Device匿名实现类的对象 39 Device d = new Device() 40 { 41 //初始化块 42 { 43 System.out.println("匿名内部类的初始化块"); 44 } 45 //实现抽象方法 46 @Override 47 public double getPrice() 48 { 49 return 56.2; 50 } 51 @Override 52 public String getName() 53 { 54 return "键盘"; 55 } 56 }; 57 ai.test(d); 58 } 59 }
上面程序创建了一个抽象父类Device类,这个抽象父类里包含两个构造器:一个无参的,一个带参的。当创建以Device为父类的匿名对象时,即可以传入参数,代表调用父类带参的构造器;也可以不传入参数,代表调用父类无参构造器。
当创建匿名内部类时,必须实现接口或抽象父类里的所有抽象方法,如果有需要,也可以重写父类中的普通方法。