四种java内部类总结

原文链接:http://forestqqqq.iteye.com/blog/1906653

原文链接:

第一 成员内部类

定义在另一个类的内部,而且与成员方法和属性平级叫成员内部类。

1成员内部类中不能存在static关键字,即,不能声明静态属性、静态方法、静态代码块等。

2在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法”和“外部类名.this.成员属性”的形式

3创建成员内部类的实例使用“外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)”的形式。在创建内部类实例之前需要先创建外部类的实例对象。

 

Java代码   收藏代码

    package test5;  
       
    public class MyTest {  
        public static void main(String[] args) {  
           Outer outer=new Outer("test");  
           Outer.Inner inner = outer.new Inner(20);  
        }  
    }  
       
    class Outer{  
        Outer(String str){  
            
        }  
        protected class Inner{  
           public Inner(int a){  
                
           }  
        }  
    }  

 

 

4成员内部类可以可以使用public,protected,default,private,static,final,abstract来修饰.当然了,被static修饰的内部类,是静态内部类。

5内部类在编译之后生成一个单独的class文件,里面包含该类的定义,所以内部类中定义的方法和变量可以跟父类的方法和变量相同。例如上面定义的三个类的class文件分别是:MyTest.class、Outer.class和Outer$Inner.class三个文件。内部类的定义文件名形式是“外部类定义名$内部类定义名”,即Outer$Inner.class。该文件反编译之后的代码是:

 

Java代码   收藏代码

    package test5;  
       
    public class Outer$Inner  
    {  
      public Outer$Inner(Outer paramOuter, int a)  
      {  
      }  
    }  

 

 

6外部类无法直接访问成员内部类的方法和属性,只能通过“内部类实例名.方法名(参数)”和“内部类实例名.属性名”的形式访问内部类的方法和属性

 

Java代码   收藏代码

    package test5;  
       
    public class MyTest {  
        public static void main(String[] args) {  
           Outer outer=new Outer("test");  
           outer.test();  
        }  
    }  
       
    class Outer{  
        private Inner inner;  
        Outer(String str){  
           //创建内部类实例  
           inner = new Inner(10);  
        }  
        public void test(){  
           //只能通过实例访问方法和属性  
           inner.print();  
        }  
        protected class Inner{  
           public Inner(int a){  
                
           }  
           public void print(){  
               System.out.println("Inner");  
           }  
        }  
    }  

 

 

7与外部类平级的类继承内部类时,其构造方法中需要传入父类的实例对象。且在构造方法的第一句调用“外部类实例名.super(内部类参数)”。

如:

 

Java代码   收藏代码

    package test5;  
       
    public class MyTest {  
        public static void main(String[] args) {  
           Outer outer = new Outer("test");  
           new Extender(outer,10);  
        }  
    }  
       
    class Outer{  
        Outer(String str){}  
        protected class Inner{  
           public Inner(int a){  
           }  
        }  
    }  
       
    class Extender extends Outer.Inner{  
        public Extender(Outer outer,int a){  
           //外部类实例名.super(内部类参数列表)  
           outer.super(a);  
        }  
    }  

 

 

第二 静态内部类

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

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

2静态内部类不能访问外部类的非静态的属性和方法。外部类不能访问内部类的非静态的属性和方法。

3静态内部类创建实例的形式:外部类名.内部类名 实例名 = new外部类名.内部类名(参数)

Java代码  收藏代码

    class Outer {  
        static class Inner {  
            void go() {  
                System.out.println("Inner class reference is: " + this);  
            }  
        }  
    }  
       
    public class Test {  
        public static void main(String[] args) {  
            Outer.Inner n = new Outer.Inner();  
            n.go();  
        }  
    }  


第三 局部内部类

定义在代码块、方法体内、作用域(使用花括号“{}”括起来的一段代码)内的类叫局部内部类。

1局部内部类只能在代码代码块、方法体内和作用域中使用(创建对象和使用类对象).

如:

 

Java代码   收藏代码

    package test5;  
       
    public class MyTest {  
        public static void main(String[] args) {  
            
        }  
    }  
       
    class Outer{  
        Outer(String str){}  
        {  
           class Inner{  
               public Inner(int a){  
               }  
           }  
           System.out.println("Inner.class.getName()=="+Inner.class.getName());  
        }  
        public void test(){  
           //这是错误的,局部内部类只在本作用域中可见  
           //System.out.println("Inner.class.getName()=="+Inner.class.getName());  
        }  
    }  

 

 

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

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

4局部内部类的定义可以使用abstract修饰,声明为抽象类。

第四 匿名内部类

1匿名内部类定义和实例化形式如下:

new父类构造方法(参数){

         //注:该方法名必须在父类中已经存在

修饰符 返回参数类型 方法名(参数列表){

 

}

}

2匿名内部类只能和new连用,用于创建一个实例。匿名内部类只能使用一次,创建实例之后,类定义会立即消失(想要多次使用就要用到反射的知识了)。

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

如:

Java代码   收藏代码

    public class InnerClassTest {  
        public static void main(String[] args) {  
           //定义一个匿名内部类,并实例化对象  
           Test test = new Test(){  
               @Override  
               public void print() {  
                  System.out.println("匿名内部类实现父类所有的抽象方法!");  
                   
               }  
           };  
           test.print();  
           System.out.println("匿名内部类的类名:test.getClass().getName()=="+test.getClass().getName());  
           System.out.println("父类的类名:Test.class.getName()=="+Test.class.getName());  
        System.out.println("test.getClass().equals(Test.class)=="+test.getClass().equals(Test.class));  
        System.out.println("test.getClass().getSuperclass().equals(Test.class)=="+test.getClass().getSuperclass().equals(Test.class));  
        }  
    }  
    abstract class Test{  
        public abstract void print();  
    }  

 

运行结果:

Java代码   收藏代码
  1. 匿名内部类实现父类所有的抽象方法!  
  2. 匿名内部类的类名:test.getClass().getName()==test5.InnerClassTest$1  
  3. 父类的类名:Test.class.getName()==test5.Test  
  4. test.getClass().equals(Test.class)==false  
  5. test.getClass().getSuperclass().equals(Test.class)==true  

 

 

InnerClassTest$1.class文件反编译之后的结果如下,证明它确实是继承了父类:

Java代码   收藏代码

    class InnerClassTest$1 extends Test  
    {  
      public void print()  
      {  
        System.out.println("匿名内部类实现父类所有的抽象方法!");  
      }  
    }  

 

4匿名内部类不能是抽象类,因为匿名内部类在定义之后,会立即创建一个实例。

5匿名内部类不能定义构造方法,匿名内部类没有类名,无法定义构造方法,但是,匿名内部类拥有与父类相同的所有构造方法。

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

如下:

Java代码   收藏代码
    public class InnerClassTest {  
        public static void main(String[] args) {  
           //定义一个匿名内部类,并实例化对象  
           Test test = new Test(){  
               {  
                  System.out.println("匿名内部类的代码块");  
               }  
               public void print(){  
                  System.out.println("匿名内部类的print方法");  
               }  
           };  
           test.print();  
        }  
    }  
    class Test{  
        public void print(){  
           System.out.println("class Test的print方法");  
        }  
    }  

 
    public class InnerClassTest {  
        public static void main(String[] args) {  
           //定义一个匿名内部类,并实例化对象  
           Test test = new Test(){  
               {  
                  System.out.println("匿名内部类的代码块");  
               }  
               public void print(){  
                  System.out.println("匿名内部类的print方法");  
               }  
           };  
           test.print();  
        }  
    }  
    class Test{  
        public void print(){  
           System.out.println("class Test的print方法");  
        }  
    }  

 


输出结果为:

Java代码   收藏代码
  1. 匿名内部类的代码块  
  2. 匿名内部类的print方法  

 

7匿名内部类中可以定义新的方法和属性(不能使用static修饰),但是无法显式的通过“实例名.方法名(参数)”的形式调用,因为使用new创建的是“上转型对象”。

注:

上转型对象特点:

<!--[if !supportLists]-->①     <!--[endif]-->父类声明指向子类对象,形式:

父类名(父接口名) 上转型实例名 = new 子类构造方法(参数);

<!--[if !supportLists]-->②     <!--[endif]-->子类可以重写父类的方法,上转型实例调用的方法只能是子类重写父类的方法或者父类的方法,不能调用子类独有的方法。

<!--[if !supportLists]-->③     <!--[endif]-->上转型对象可以强制转换成子类对象:形式:子类名 实例名 = (子类名)上转型对象;

转换成子类对象之后,与“new 子类构造方法(参数)”形式定义的对象无区别。

虽然不能通过“实例名.方法名(参数)”的形式调用子类独有的方法,但是可以通过反射来调用:

Java代码   收藏代码

    package test5;  
       
    import java.lang.reflect.InvocationTargetException;  
    import java.lang.reflect.Method;  
       
    public class InnerClassTest {  
        public static void main(String[] args)  
               throws SecurityException, NoSuchMethodException,  
               IllegalArgumentException, IllegalAccessException,  
               InvocationTargetException {  
           //定义一个匿名内部类,并实例化对象  
           Test test = new Test(){  
               //匿名内部类中可以定义属性  
               private int a;  
               //匿名内部类中可以定义方法  
               public void xxx() {  
                   System.out.println("xxx方法");  
               }  
               //匿名内部类中可以重写父类的方法  
               public void print() {  
                  a = 10;  
               }  
           };  
            
           //通过反射调用子类方法  
           Class c = test.getClass();  
           Method m = c.getMethod("xxx");  
           m.invoke(test);  
        }  
    }  
    class Test{  
        public void print(){  
           System.out.println("父类方法");  
        }  
    }  

 

8匿名内部类访问外部类的局部变量,则该局部变量需要使用final声明。匿名内部类中访问外部类的成员方法和属性使用“外部类名.this.方法名(参数)”和“内部类名.this.属性名”的形式。

Java代码   收藏代码
package test5;  
   
public class InnerClassTest {  
    private int a;  
    public static void main(String[] args) {  
       new InnerClassTest().go();  
    }  
    public void go(){  
       a = 100;  
       //外部类的局部变量  
       final int b=10;  
       Test test = new Test(){  
           public void print() {  
              //匿名内部类访问外部类的属性  
              System.out.println("InnerClassTest.this.a=="+InnerClassTest.this.a);  
              //匿名内部类中访问外部类的局部变量  
              System.out.println("b=="+b);  
           }  
       };  
       test.print();  
    }  
}  
abstract class Test{  
    public abstract void print();  
}  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值