1 //79-80-面向对象-内部类-体现 2 /* 3 当A类中的内容要被B类直接访问,而A类还需要去创建B类的对象,访问B的内容时, 4 这时可以将B类定义到A类的内部,这样访问更为便捷。 5 6 将B类称之为内部类(内置类,嵌套类). 7 8 访问方式总结: 9 内部类可以直接访问外部类中的所有成员,包含私有的。 10 而外部类要想访问内部类中的成员,必须创建内部类对象。 11 12 当描述事物时,事物的内部还有事物时,而这个内部的事物还在访问外部事物中的内容。 13 这时就将这个事物通过内部类来体现。 14 15 16 【内部类被访问的方式】 17 情况一:内部类在成员位置上的被访问方式。 18 成员是可以被指定的修饰符所修饰的。 19 public :不多见,因为更多的时候,内部类已经被封装到了外部类中,不直接 20 对外提供。 21 static: 22 */ 23 24 class Outer//外部类 25 { 26 private static int num = 4; 27 28 public class Inner//内部类 29 { 30 // static final int x = 3; 31 void show() 32 { 33 System.out.println("num="+num); 34 } 35 static void show1(){}//非静态内部类中不允许定义静态成员。仅允许在 36 //非静态内部类中定义常量。(final) 37 //如果想要在内部类中定义静态成员,那么内部类也必须 38 //别静态修饰。 39 } 40 41 /* 42 内部类被静态修饰后,随着Outer的加载而加载,可以把一个静态内部类理解为就是一个外部类。 43 */ 44 static class Inner2 45 { 46 void show2() 47 { 48 System.out.println("Inner2 show2 run..."+num); 49 } 50 static void staticShow() 51 { 52 System.out.println("Inner2 staticShow run"); 53 } 54 } 55 void method() 56 { 57 //Outer.Inner in = new Outer.Inner();//这样写也是可以的。 58 Inner in = new Inner(); 59 in.show(); 60 } 61 } 62 63 class Inner 64 { 65 public static void main(String[] args) 66 { 67 // Outer out = new Outer(); 68 // out.method(); 69 70 //测试情况一:直接访问Outer类中的内部类的非静态成员。 71 72 //创建内部类的对象就可以了,内部类作为成员,应该先有外部类对象,再有内部类对象。 73 // Outer.Inner in = new Outer().new Inner(); 74 // in.show(); 75 76 //测试二:对静态内部类中的非静态成员进行调用,如何弄? 77 //因为内部类是静态,所以不需要创建Outer的对象,直接创建内部类对象就行了。 78 // Outer.Inner2 in = new Outer.Inner2(); 79 // in.show2(); 80 81 //如果静态内部类中有静态成员该如何访问呢?既然静态内部类已随外部类加载,而且 82 //静态成员随着类的加载而加载,这时就不需要对象,直接用类名调用即可。 83 Outer.Inner2.staticShow(); 84 85 } 86 }
1 //81-面向对象内部类访问外部类的原因。 2 /* 3 为什么内部类就能直接访问外部类中的成员呢? 4 那是因为内部类持有了外部类的引用 外部类.this 5 6 对于静态内部类不持有 外部类.this 而是直接使用外部类名。 7 */ 8 class Outer 9 { 10 int num = 3; 11 12 class Inner 13 { 14 int num = 4; 15 void show() 16 { 17 int num = 5; 18 System.out.println("num="+num); 19 System.out.println("num="+this.num); 20 System.out.println("num="+Outer.this.num); 21 } 22 } 23 void method() 24 { 25 //System.out.println(/*Outer.this.*/num); 26 new Inner().show(); 27 } 28 } 29 class InnerClassDemo2 30 { 31 public static void main(String[] args) 32 { 33 Outer out = new Outer(); 34 out.method(); 35 } 36 }
1 /* 2 内部类其实也可以定义在外部类的局部变量位置上。 3 4 内部类定义在局部时,只能访问被final修饰的局部变量。 5 为啥呢?因为编译生成的class中直接操作那个最终的数值了。 6 所以可以访问final,因为其值不会变化。 7 8 为什么不能访问非最终的局部变量呢? 9 */ 10 class Outer 11 { 12 int num = 3; 13 // Object obj; 14 15 void method() 16 { 17 int x = 5;//局部变量。省略的final修饰符。 18 // x = 4; //编译失败,因为x默认为final的。 19 int y = 3; 20 class Inner//局部内部类。不能被成员修饰符修饰。 21 { 22 void show() 23 { 24 System.out.println("x="+x); 25 System.out.println("x="+y);//若y没有加默认的final修饰符,则 26 //访问失败,因为y的声明周期太短了。 27 System.out.println("Inner show run..."+num); 28 } 29 } 30 new Inner.show(); 31 // obj = new Inner(); 32 } 33 } 34 35 class Outer2 36 { 37 Object obj; 38 public void method() 39 { 40 int y = 9; 41 class Inner//extends Object 42 { 43 //覆盖了toString方法 44 public String toString() 45 { 46 return "tostring"+y;//假设可以访问。 47 } 48 } 49 obj = new Inner();//给obj赋一个Inner对象。 50 } 51 public void function() 52 { 53 System.out.println(obj.toString()); 54 } 55 } 56 57 class InnerClassDemo5 58 { 59 public static void main(String[] args) 60 { 61 Outer out = new Outer(); 62 out.method(); 63 } 64 }
1 //83-84内部类-内部类的继承或者实现&匿名内部类。 2 /* 3 看API,发现类名或者接口的名称中有 . 说明是内部类,或者内部接口。 4 5 内部了的延伸。 6 内部类是可以继承或者实现外部其他的类或者接口的。 7 8 好处在于,通过内部类的方式对类进行继承重写,或者接口进行实现。 9 通过公共的方式对其内部类对象进行访问,因为通常内部类很有可能被外部类封装其中。 10 我们就可以通过接口的方式访问到内部类。 11 12 13 对以下代码进行简化。 14 匿名内部类,其实就是一个带有内容的子类对象。 15 格式: new 父类or接口()(子类内容。) 16 17 匿名内部类就是内部类的简化形式。 18 别忘了,凡是简化的都有局限性。匿名内部类有前提, 19 匿名内部类必须继承父类或者实现接口。 20 */ 21 22 //定义一个抽象的外部类。 23 abstract class AbsDemo 24 { 25 abstract void show(); 26 } 27 28 class Outer 29 { 30 int num = 3; 31 /* 32 class Inner extends AbsDemo 33 { 34 //重写抽象方法show。 35 void show() 36 { 37 System.out.println("num="+num); 38 } 39 } 40 41 //获取内部类的对象。 42 public AbsDemo getObject()//多态:AbsDemo abs = new Inner(); 43 { 44 return new Inner(); 45 } 46 */ 47 public void method() 48 { 49 // new Inner().show(); 50 /* 51 不想创建具体的子类型,还想创建AbsDemo的子类对象。 52 怎么实现呢?没有子类型,干脆直接使用父类型就可以了。 53 可是在该例子中是抽象类,怎么可以new对象呢? 54 抽象类之所以不能new对象,是因为抽象方法没有被覆盖。只要 55 重写不就可以了吗? 56 */ 57 new AbsDemo()//这就是一个AbsDemo的子类对象。只不过这个对象有点胖。 58 //这是一个带着内容的子类对象。 59 //这种写法有一个称呼,叫做【匿名内部类】。 60 { 61 //直接就重写抽象的show方法。 62 void show() 63 { 64 System.out.println("num==="+num); 65 } 66 }.show(); 67 } 68 } 69 70 class InnerClassDemo4 71 { 72 public static void main(String[] args) 73 { 74 //Outer out = new Outer(); 75 // out.method(); 76 77 //如果Inner对外提供,可以如此获取。 78 //Outer.Inner in = out.getObject(); 79 //in.show(); 80 81 //如果Inner被private,可以通过父类型获取。 82 //AbsDemo a = out.getObject(); 83 //a.show(); 84 85 Outer out = new Outer(); 86 out.method(); 87 } 88 }
1 //86-内部类-匿名内部类的使用。 2 interface Inter 3 { 4 void show1(); 5 void show2(); 6 //方法超过两个,建议不要写成匿名内部类。 7 } 8 9 class Outer 10 { 11 int num = 4; 12 13 //在一个类中使用一个接口,可以通过内部类来实现。 14 /* 15 class Inner implements Inter 16 { 17 public void show1(){} 18 public void show2(){} 19 } 20 */ 21 public void method() 22 { 23 /* 24 Inner in = new Inner(); 25 in.show1(); 26 in.show2(); 27 */ 28 29 //对其简化,写成匿名内部类的形式。 30 Inter in = new Inner()//多态,父类的引用指向了子类对象。 31 { 32 public void show1(){} 33 public void show2(){} 34 }; 35 in.show1(); 36 in.show2(); 37 } 38 } 39 class InnerClassDemo5 40 { 41 public static void main(String[] args) 42 { 43 System.out.println("Hello World!"); 44 } 45 }
1 //87-匿名内部类练习。 2 interface Inter 3 { 4 public void show(); 5 } 6 7 class Outer 8 { 9 //代码补足。要求使用匿名内部类。 10 public static Inter method() 11 { 12 //既然在Outer类中使用到了Inter对象,可以使用内部类来完成。 13 //需要子类型,只要简化形式即可,因为接口中就只有一个方法。 14 15 /* 16 return new Inter() 17 { 18 public void show() 19 { 20 code...; 21 } 22 }; 23 */ 24 // return this.new Inter(); 25 // } 26 27 //还原成内部类。当静态方法访问内部类时,内部类必须是静态的。 28 /* static class Inner implements Inter 29 { 30 public void show(){} 31 } 32 */ 33 } 34 } 35 36 //面试题: 37 class Outer2 38 { 39 public void method() 40 { 41 //以下两个对象有区别吗? 42 new Object()//当new Object();时,是创建Object对象,而写成new Object(){}时,创建 43 //的是Object的子类对象。 44 { 45 public void show(){} 46 }.show();//这个可以编译通过 47 48 Object obj = new Object() 49 { 50 public void show(){} 51 }; 52 obj.show();//编译失败。为啥呢?因为匿名内部类是子类对象,当Object obj指向 53 //时,就被提升了,而Object类中没有定义show()方法。编译失败。 54 55 } 56 /* 57 //写一个内部类。 58 class Inner extends Object//有父类,可以简化成匿名内部类。 59 { 60 public void show(){} 61 } 62 */ 63 } 64 65 class InnerClassDemo7 66 { 67 public static void main(String[] args) 68 { 69 Outer.method().show(); 70 /* 71 Outer.method():Outer类中有一个method方法,这个方法时静态的。 72 Outer.method().show():能调用show()的必然是对象。说明method方法运算完应 73 该放回一个对象,而且能调用Inner中的方法,说明 74 这个对象类型是Inner的。 75 */ 76 } 77 }