Java——内部类的定义以及使用

内部类:在类内部进行其他类结构嵌套操作。

举栗说明:

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();
    }
}

提出来之后我们发现代码变得更加麻烦,难理解,此时我们在这里可以提一下内部类的优点:

  • 内部类的优点
a.内部类与外部类可以方便的访问彼此的私有域(包含私有方法,私有属性)
存在私有内部类(静态,成员均可)
【ArrayList中Node内部类,HashMap中Entry内部类(私有内部类)】
b.内部类是另外一种封装(保护性),对外部的其他类隐藏(心脏包在人身体内部)
c.内部类可以实现Java单继承的局限。

- 使用内部类实现Java的多继承:

class A{
    private String msg = "test";
    public String getMsg(){
        return msg;
    }
}
class B{
    private int age = 20;
    public int getAge(){
        return age;
    }
}
class C{
    class InnerClassA extends A{
        public String name(){
            return super.getMsg();
        }
    }
    class InnerClassB extends B{
        public int age(){
            return super.getAge();
        }
    }
    public String name(){
        return new InnerClassA().name();
    }
    public int age(){
        return new InnerClassB().age();
    }
}
public class Test{
    public static void main(String[] args){
        C c = new C();
        System.out.println(c.name());
        System.out.println(c.age());
    }
}

多继承还是推荐多层继承。

- 内部类和外部类的关系:(不推荐使用)

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();
    }
}
程序运行结果:
//InnerClass

1.说明了内外部类可以直接访问彼此的私有属性,首先必须创建外部类,才能创建内部类,创建内部类的时候就把外部类的对象传进来了 ,所以可以直接用。
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.如果发现类名称上出现了“ . “,应当立即想到内部类的概念。

猜你喜欢

转载自blog.csdn.net/qq_41420688/article/details/83377063