你的位置:首页 > Java教程

[Java教程]Java学习(十六)、成员内部类,静态内部类,匿名内部类,局部内部类

定义:将一个类定义在另一个类的内部。内部的类称为内部类;

public class Outer{

           class inner{

         //省略

}

}

 

特点

①   内部类可以很好的实现隐藏,可以使用protected,private修饰符;

②   内部类可以直接访问外部类的所有成员,包括私有成员;

③   外部类不能直接访问内部类的成员,必须首先要建立内部类的对象才能访问;

④   内部类可以解决一些问题,比如间接的去实现多继承。可以避免修改接口而实现同一个类中两种同名方法的调用;

 

成员内部类及应用

成员内部类特点

①   成员内部类属于外部类的实例成员,成员内部类都可以有public,private,default,protected权限修饰符。在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法”和“外部类名.this.成员属性”的形式;

②   创建成员内部类的实例使用“外部类名.内部类名.实例名=外部类实例名. new 内部类构造方法(参数)”的形式;

成员内部类有以下限制

①   成员内部类不能与外部类重名;

②   不能在成员内部类中定义static属性、方法和类(static,final形式的常量定义除外)。因为一个成员内部类实例必然与一个外部类实例关联,static成员完全可移到其外部类中去;

 1 public class MemberInnerClass{ 2   public static void main(String []args){ 3     //创建外部类对象 4     Outer1 outer=new Outer1(); 5     //创建内部类对象 6     Outer1.Inner1 inner=outer.new Inner1(); 7     inner.innerShow(); 8      9     System.out.println("--------------外部类访问内部类对象--------------");10     outer.outerShow();11   }12 }13 14 class Outer1{15   private String name="张三";16   private int num1=10;17   public void outerShow(){18     System.out.println(name);19     System.out.println(num1);20     //System.out.println(num2);//外部类不能直接访问内部类的成员21     22     //外部类访问内部类对象23     Inner1 inner =new Inner1();24     inner.innerShow();25   }26   27   //当内部类改成私有时private,仅能在外部类中访问28   public class Inner1{29     private String name="李四";30     private int num2=20;31     private static final int num3=30;//静态常量在内部类中是可以使用的32     //private static int num3=30;//在成员内部类中不能声明静态成员和静态方法33     public void innerShow(){34       System.out.println(name);35       System.out.println(num2);36       37       //成员内部类可以直接访问外部类的属性和方法,包括私有的38       System.out.println("--------------");39       //外部类访问内部类时注释outerShow(),避免死循环40       //outerShow();41       42       //打印外部类中成员属性43       System.out.println("--------------打印外部类中成员属性--------------");44       System.out.println(Outer1.this.name);45       System.out.println(Outer1.this.num1);46     }47   }48 }

View Code

用内部类间接实现多继承

 1 public class MultiExtendsDemo{ 2   public static void main(String []args){ 3     C c=new C(); 4     //间接实现多继承 5     c.showA(); 6     c.showB(); 7   } 8 } 9 10 class A{11   public void showA(){12     System.out.println("A");13   }14 }15 16 class B{17   public void showB(){18     System.out.println("B");19   }20 }21 22 class C{23   private class A1 extends A{24     public void showA(){25       super.showA();26     }27   }28   29   private class B1 extends B{30     public void showB(){31       super.showB();32     }33   }34   35   public void showA(){36     new A1().showA();37   }38   39   public void showB(){40     new B1().showB();41   }42 }

View Code

父类中和接口中的方法名相同

为了不更改其方法且要实现这个2个方法

采用内部类的方式来实现

 1 public class Demo2{ 2   public static void main(String []args){ 3     Son son=new Son(); 4     son.show(); 5     son.show2(); 6   } 7 } 8  9 abstract class Parent{10   public abstract void show();11 }12 13 interface IShow{14   public abstract void show();15 }16 17 /*class Son extends Parent implements IShow{18   public void show(){19     20   }21   public void show1(){22     23   }24 }*/25 26 //因为父类中和接口中的方法名相同27 //为了不更改其方法且要实现这个2个方法28 //采用内部类的方式来实现29 //但最好的方式还是改方法30 class Son extends Parent{31   public void show(){32     System.out.println("抽象类中的show方法");33   }34   35   private class Inner2 implements IShow{36     public void show(){37       System.out.println("接口中的show方法");38     }39   }40   41   public void show2(){42     Inner2 inner=new Inner2();43     inner.show();44   }45 }

View Code

 

静态内部类及其应用

静态内部类特点

①   使用static修饰的成员内部类叫静态内部类;

②   静态内部类跟外部类没有任何关系,只是在生成类名和类定义时有影响。静态内部类可以看作是与外部类平级的类。使用方式与外部类平级的类完全相同;

③   创建静态内部类的实例使用  外部类名.内部类名. 实例名=new 外部类名.内部类名(参数);

静态内部类有以下限制

①   静态内部类的名字不能与外部相同;

②   静态内部类不能访问外部类的非静态的属性和方法,外部类不能访问内部类的非静态的属性和方法;

 1 public class StaticInnerClass{ 2   public static void main(String []args){ 3     Outer2.Inner2 inner=new Outer2.Inner2();//构造一个静态内部类对象 4     inner.innerShow(); 5      6     Outer2 outer=new Outer2(); 7     outer.outerShow(); 8   } 9 }10 11 class Outer2{12   private String name="张三";13   private int num1=10;14   private static int num3=100;15   public void outerShow(){16     System.out.println(name);17     System.out.println(num1);18     19     //System.out.println(Inner2.name);20     Inner2 inner =new Inner2();21     System.out.println(inner.name);//访问非静态22     23     System.out.println(Inner2.num3);//访问静态24   }25   26   public static class Inner2{27     private String name="李四";28     private int num2=20;29     private static final int num3=30;30     31     public void innerShow(){32       System.out.println(name);33       System.out.println(num2);34       35       //System.out.println(Outer2.this.name);//静态内部类不能访问外部类的非静态成员36       System.out.println(Outer2.num3);37       System.out.println(num2);38     }39   }40 }

View Code

 

匿名内部类及应用

匿名内部类特点

①   匿名内部类时没有名称的内部类,没办法引用它们。必须在创建时,作为new语句的一部分来声明并创建它们的实例;

②   匿名内部类必须继承一个类(抽象的,非抽象的都可以)或者实现一个接口。如果父类(或父接口)是抽象类,则匿名内部类必须实现其所有抽象方法;

③   匿名内部类中可以定义代码块,用于实例的初始化,但是不能定义静态代码块;

匿名内部类的语法:new interface/superclass(){//类体}

这种形式的new语句声明一个新的匿名类,它对一个给定的类进行扩展,或者实现一个给定的接口,并同时创建该匿名类的一个新实例;

不使用匿名内部类时

 1 public class AnonymousInnerClass{ 2   public static void main(String []args){ 3     Person person=new Person(); 4     Animal dog=new Dog(); 5     person.feed(dog); 6   } 7 } 8  9 abstract class Animal{10   public abstract void eat();11 }12 13 class Person{14   public void feed(Animal animal){15     animal.eat();16   }17 }18 19 class Dog extends Animal{20   public void eat(){21     System.out.println("啃骨头");22   }23 }

View Code

使用匿名内部类

 1 public class AnonymousInnerClass{ 2   public static void main(String []args){ 3     Person person=new Person(); 4     //Animal dog=new Dog(); 5     //person.feed(dog); 6      7     /*Animal dog=*/new IAnimal(){ 8       private String name="aa"; 9       10       //代码块11       {12         name="哈哈";13       }14       15       //不能使用静态代码块16       //static{}17       public void eat(){18         System.out.println("啃骨头");19       }20       public void show(){21         System.out.println(name);22       }23     }.show();//调用内部的show();24     25     //person.feed(dog);26     //dog.show();//这里不能调用定义的show();27     //person.feed(dog);28     person.feed(new IAnimal(){29       public void eat(){30         System.out.println("吃鱼");31       }32     });33   }34 }35 36 //抽象类37 //使用接口时先注释38 //并修改Person类中的Animal为IAnimal39 /*abstract class Animal{40   public abstract void eat();41 }*/42 43 //接口44 interface IAnimal{45   public abstract void eat();46 }47 48 class Person{49   public void feed(IAnimal animal){50     animal.eat();51   }52 }53 54 /*class Dog extends Animal{55   public void eat(){56     System.out.println("啃骨头");57   }58 }*/

View Code

局部内部类及应用

局部内部类的特点

①   定义在代码块、方法体内的类叫局部内部类;

②   局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”和“外部类名.this.方法名(参数)”的形式;

③   对外部世界完全隐藏,只能在其作用域内生成对象;

 

局部内部类有以下限制

①   局部内部类不能加访问修饰符,因为它们不能类成员;

②   成员内部类不能与外部类重名;

③   局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰;

 1 public class LocalInnerClass{ 2   public static void main(String []args){ 3     Outer3 outer=new Outer3(); 4     outer.showOuter(); 5   } 6 } 7  8 class Outer3{ 9   private String name="张三";10   private int num1=10;11   private static int num2=20;12   public void showOuter(){13     /*final*/ int num4=50;//这里加不加final都可以被内部类访问?希望看到的且知道的帮我解答下14     //局部内部类不能加访问修饰符15     class Inner3{16       private int num3=30;17       private int num1=20;18       public void showInner(){19         System.out.println(num3);20         System.out.println(num1);21         22         System.out.println(Outer3.this.num1);23         System.out.println(Outer3.num2);24         25         System.out.println(num4);26       }27     }28     Inner3 inner=new Inner3();29     inner.showInner();30   }31 }

View Code