举栗说明:
class Outter{ private String msg = "Outter中的字符串"; //内部类 class Inner{ private String inMsg = "Inner中的字符串"; public void fun(){ //直接调用外部类的私有属性 System.out.println(msg); } } public void test(){ //生产内部类对象 Inner in = new Inner(); in.fun(); } } public class Test{ public static void main(String[] args){ Outter out = new Outter(); out.test(); } }缺点:结构复杂 将Inner类提出来,主方法不变,实现相同的功能:
class Outter{ private String msg = "Outter中的字符串"; //因为这里是private属性,所以不能直接访问,需提供getter方法 public String getMsg(){ return this.msg; } public void test(){ //this表示当前对象 Inner in = new Inner(this); in.fun(); } } class Inner{ private String inMsg = "Inner中的字符串"; private Outter out; //通过构造方法给Inner内传入一个Outter类,专业叫做【构造注入】 //此时Outter是Inner内的普通属性 public Inner(Outter out){ //这里的Outter out就是一个参数 this.out = out; //为Inner中的out变量初始化 } public void fun(){ System.out.println(out.getMsg()); } } public class Test{ public static void main(String[] args){ Outter out = new Outter(); out.test(); } }提出来之后我们发现代码变得更加麻烦,难理解,此时我们在这里可以提一下内部类的优点:
内部类的优点:多继承还是推荐多层继承。
1.对于非静态内部类,内部类的创建需要依赖外部类对象,在没有外部类实例之前无法创建非静态内部类。
2.内部类是一个相对独立的个体,与外部类没有is-a关系。
3.内部类可以直接访问外部类的元素(包含私有域),但是外部类不可以直接访问内部类元素,需要通过内部类的引用间接访问。
针对于第三点:
class Outter{ private String msg; private int age; //-----------------内部类----------------- class Inner{ public void display(){ msg = "test"; //直接使用 //Outter.this.msg = "test"; age = 20; //直接使用 //Outter.this.age = 20; System.out.println(msg); System.out.println(age); } } //---------------- ------------------------- public void test(){ Inner in = new Inner(); in.display(); } } public class Test{ public static void main(String[] args){ Outter out = new Outter(); out.test(); } }内外部类可以直接访问彼此的私有属性:
class Outter{ //------------------------------------- class Inner{ //1... private String msg = "InnerClass"; } //----------------------------------------- public void test(){ Inner in = new Inner();//2... System.out.println(in.msg); } } public class Test{ public static void main(String[] args){ Outter out = new Outter(); out.test(); } } 程序运行结果: //InnerClass1.说明了内外部类可以直接访问彼此的私有属性,首先必须创建外部类,才能创建内部类,创建内部类的时候就把外部类的对象传进来了 ,所以可以直接用。 2.外部类访问内部类需要创建内部类的对象以后才能用,这叫间接使用。
a.创建非静态内部类
外部类.内部类 内部类引用 = new 外部类().new 内部类(); Outter.Inner in = new Outter().new Inner();b.创建静态内部类
外部类.内部类 内部类引用 = new 外部类.内部类(); Outter.Inner in = new Ourtter.Inner();1.成员内部类(重点)(成员方法)
a.成员内部类不能存在任何static变量或方法,可以访问外部类的静态域。 b.成员内部类是依附外部类的,所以只有先创建了外部类才能创建内部类。
(成员内部类不能拥有静态域,但可以访问外部静态域)
class Outter{ private String name = "test"; private static int age = 20; //-------------------成员内部类---------------- class Inner{ //private static int age = 50; //成员内部类不能存在static的变量或方法,会报错:内部类Outter.Inner中的静态声明非法。 public void fun(){ System.out.println(name); //可以访问外部类的静态或者非静态属性 System.out.println(age); } } //------------------------------------------------ } public class Test{ public static void main(String[] args){ Outter.Inner in = new Outter().new Inner(); in.fun(); } }2.静态内部类(重点)(静态方法)
和非静态内部类相比,静态内部类没有指向外部的引用。同时,非静态内部类不能声明静态成员,只有静态内部类才可以声明静态成员。 静态内部类将自动转换为顶层类(top-levelclass),即它没有父类,而且不能引用外部类成员或其他内部类成员。当一个内部类不需要引用外部类成员,只需要隐藏在另一个类中时,可以将该内部类声明为静态的。
a.静态内部类的创建不需要依赖外部类,可以直接创建。
b.静态内部类不可以使用任何外部类的非static域(包含属性与方法),但是可以存在自己的成员变量。
3.方法内部类(局部内部类)
方法内部类定义在外部类的方法中,局部内部类和成员内部类基本一致,只是作用域不同,方法内部类只能在该方法中被使用。
a.方法内部类不允许使用访问权限修饰符 public private protected 均不允许。
b.方法内部类对外部完全隐藏除了创建这个类的方法可以访问它以外,其他地方均不能访问。
c.方法内部类如果要想使用方法形参,该形参必须使用final声明(JDK8将形参变为隐式final声明)
public class Test{ public static void main(String[] args){ final int i = 8; class person{ public String name; public void show(){ System.out.println(i); System.out.println(this.name); } } person p = new person(); p.name = "zhangsan"; p.show(); } } 程序运行结果: 8 zhangsan上例中,在main方法中定义了person类,它是一个内部类。内部类方法show访问了main方法中定义的final类型的局部变量。其中,方法中内部类只能访问方法中final类型的局部变量,而不能访问其他类型的局部变量,但可以访问外部类的数据成员和成员方法。
4.匿名内部类(lamdba表达式前身)
匿名内部类就是一个没有名字的方法内部类,所以它没有构造方法(但是如果这个匿名内部类继承了只含有带参数构造方法的父类,创建它的时候就必须带上这些参数,并在实现过程中使用super关键字调用相应内容)。因此特点与方法内部类完全一样,除此之外,还有两个自己的特点:
a.匿名内部类必须继承一个抽象类或者实现一个接口。
b.匿名内部类没有构造方法,因为它没有类名。
匿名类的语法规则:
new interfacename(){...}; 或 new superclassname(){...};总结:内部类的使用暂时不作为设计的首选。
1.破坏了程序的结构。 2.方便进行私有属性的访问。(外部类可以访问内部类的私有域) 3.如果发现类名称上出现了“ . “,应当立即想到内部类的概念。