• 随笔32 内部类,外部类,局部内部类


    • 对于外部类来说,只有两种修饰,public和默认(default),因为外部类放在包中,只有两种可能,包可见和包不可见。
    • 对于内部类来说,可以有所有的修饰,因为内部类放在外部类中,与成员变量的地位一致,所以有四种可能。
    • 局部内部类就像一个局部变量,修饰符只有final和abstract.

    四种java内部类

    一:成员内部类

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

    • 成员内部类中不能存在static关键字(static修饰的是静态内部类),即,不能声明静态属性、静态方法、静态代码块等。 
    • 在成员内部类中访问外部类的成员方法和属性,要使用“外部类名.this.成员方法”“外部类名.this.成员属性”的形式 
    • 创建成员内部类的实例使用“外部类名.内部类名 实例名 = 外部类实例名.new 内部类构造方法(参数)”的形式。在创建内部类实例之前需要先创建外部类的实例对象。 
     1 public class MyTest {  
     2     public static void main(String[] args) {  
     3        Outer outer=new Outer("test");  
     4        Outer.Inner inner = outer.new Inner(20);  
     5     }  
     6 }  
     7 class Outer{  
     8     Outer(String str){  
     9         
    10     }  
    11     protected class Inner{  
    12        public Inner(int a){  
    13             
    14        }  
    15     }  
    16 }  
    • 成员内部类可以可以使用public,protected,default,private,static,final,abstract来修饰.当然了,被static修饰的内部类,是静态内部类。 
    • 内部类在编译之后生成一个单独的class文件,里面包含该类的定义,所以内部类中定义的方法和变量可以跟父类的方法和变量相同。例如上面定义的三个类的class文件分别是:MyTest.class、Outer.class和Outer$Inner.class三个文件。内部类的定义文件名形式是“外部类定义名$内部类定义名”,即Outer$Inner.class。该文件反编译之后的代码是:
    1 public class Outer$Inner  {  
    2   public Outer$Inner(Outer paramOuter, int a)  {  
    3   }  
    4 }  
    • 外部类无法直接访问成员内部类的方法和属性,只能通过“内部类实例名.方法名(参数)”“内部类实例名.属性名”的形式访问内部类的方法和属性 。
     1 public class MyTest {  
     2     public static void main(String[] args) {  
     3        Outer outer=new Outer("test");  
     4        outer.test();  
     5     }  
     6 }  
     7 class Outer{  
     8     private Inner inner;  
     9     Outer(String str){  
    10        //创建内部类实例  
    11        inner = new Inner(10);  
    12     }  
    13     public void test(){  
    14        //只能通过实例访问方法和属性  
    15        inner.print();  
    16     }  
    17     protected class Inner{  
    18        public Inner(int a){  
    19             
    20        }  
    21        public void print(){  
    22            System.out.println("Inner");  
    23        }  
    24     }  
    25 }  
    • 与外部类平级的类继承内部类时,其构造方法中需要传入父类的实例对象。且在构造方法的第一句调用“外部类实例名.super(内部类参数)”。 
     1 public class MyTest {  
     2     public static void main(String[] args) {  
     3        Outer outer = new Outer("test");  
     4        new Extender(outer,10);  
     5     }  
     6 }  
     7 class Outer{  
     8     Outer(String str){}  
     9     protected class Inner{  
    10        public Inner(int a){  
    11        }  
    12     }  
    13 }     
    14 class Extender extends Outer.Inner{  
    15     public Extender(Outer outer,int a){  
    16        //外部类实例名.super(内部类参数列表)  
    17        outer.super(a);  
    18     }  
    19 }  

    二:静态内部类

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

    • 静态内部类跟外部类没有任何关系,只是在生成类名和类定义时有影响。静态内部类可以看做是与外部类平级的类。使用方式与外部类平级的类完全相同。 
    • 静态内部类不能访问外部类的非静态的属性和方法。外部类不能访问内部类的非静态的属性和方法。
    • 静态内部类创建实例的形式:外部类名.内部类名 实例名 = new外部类名.内部类名(参数)

    三:局部内部类 

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

    • 局部内部类只能在代码代码块、方法体内和作用域中使用(创建对象和使用类对象).
     1 public class MyTest {  
     2     public static void main(String[] args) {  
     3           
     4     }  
     5 }     
     6 class Outer{  
     7     Outer(String str){}  
     8     {  
     9         class Inner{  
    10             public Inner(int a){  
    11             }  
    12         }  
    13         System.out.println("Inner.class.getName()=="+Inner.class.getName());  
    14     }  
    15     public void test(){  
    16         //这是错误的,局部内部类只在本作用域中可见  
    17         //System.out.println("Inner.class.getName()=="+Inner.class.getName());  
    18     }  
    19 }  
    • 局部内部类访问外部类的属性和方法使用“外部类名.this.属性名”“外部类名.this.方法名(参数)”的形式 。
    • 局部内部类访问作用域内的局部变量,该局部变量需要使用final修饰。 
    • 局部内部类的定义可以使用abstract修饰,声明为抽象类。 

    四:匿名内部类

    • 匿名内部类定义和实例化形式如下:
    1 new父类构造方法(参数){ 
    2          //注:该方法名必须在父类中已经存在 
    3     修饰符 返回参数类型 方法名(参数列表){ 
    4 
    5     } 
    6 } 
    • 匿名内部类只能和new连用,用于创建一个实例匿名内部类只能使用一次,创建实例之后,类定义会立即消失(想要多次使用就要用到反射的知识了)。 
    • 匿名内部类必须继承一个类(抽象的、非抽象的都可以)或者实现一个接口。如果父类(或者父接口)是抽象类,则匿名内部类必须实现其所有抽象方法。 
    • 匿名内部类不能是抽象类,因为匿名内部类在定义之后,会立即创建一个实例。
    • 匿名内部类不能定义构造方法,匿名内部类没有类名,无法定义构造方法,但是,匿名内部类拥有与父类相同的所有构造方法。 
    • 匿名内部类中可以定义代码块,用于实例的初始化,但是不能定义静态代码块。 
    • 匿名内部类中可以定义新的方法和属性(不能使用static修饰),但是无法显式的通过“实例名.方法名(参数)”的形式调用,因为使用new创建的是“上转型对象”。
    • 匿名内部类访问外部类的局部变量,则该局部变量需要使用final声明。匿名内部类中访问外部类的成员方法和属性使用“外部类名.this.方法名(参数)”“内部类名.this.属性名”的形式。
    • 匿名内部类不能重写父类的静态方法。
  • 相关阅读:
    Python 之解析配置文件模块ConfigParser
    SonarQube代码质量管理平台
    SVN代码统计工具StatSVN
    python 3接口测试
    python+selenium使用chrome时,报错ignore certificate errors
    python3发送邮件(有附件)
    日记
    杂记 包含 serialize().ajaxStart() .ajaxStop()以及其他
    还是要说一下XML。全当日记
    桑心!XML
  • 原文地址:https://www.cnblogs.com/lyr612556/p/7828455.html
Copyright © 2020-2023  润新知