Java的内部类

初识java内部类

内部类:指的是在Java中可以将一个类定义在另一个类的内部。

  • 内部类可以定义在 类的内部 (与类成员层次一致)
  • 内部类可以定义在 方法/块内部 (与类成员相差一个层次,与方法的局部变量是一个层次)

*1.成员内部类

将一个类直接定义在类的里面,作为成员,与属性或方法层次一致。
成员内部类可以与正常类一样 使用不同的修饰符(权限的 ,特征的都行)来修饰
外部类只能使用两种权限修饰符,(public ,默认不写)
而内部类可以使用全部的四种权限修饰符,(public, protected ,默认不写 ,private)
好处1.省略了一个.java源文件
好处2.成员内部类中可以访问外部类的所有成员 ,包括私有的

public class Demo {
    private String name = "这是正常类中的属性";
    public void testDemo(){
        System.out.println("这是正常类中的方法");
    }
    //成员内部类
    public class InnerDemo{
        public void testInnerDemo(){
            System.out.println("我是成员内部类的方法"+name);
            testDemo();
        }
    }
}
    public static void main(String[] args) {
        //创建内部类的对象---调用内部类的方法
        Demo.InnerDemo innerDemo = new Demo().new InnerDemo();
        //调用内部类的方法
        innerDemo.testInnerDemo();
    }

输出结果:
在这里插入图片描述
若想要在内部类中通过对象.的方式调用外部类成员,方式为: 外部类.this.外部类成员;

public class Demo {
    private String name = "这是正常类中的属性";
    public void testDemo(){
        System.out.println("这是正常类中的testDemo方法");
    }
    //成员内部类
    public class InnerDemo{
        private String name = "我是内部类的属性";
        public void testDemo(){
            System.out.println("这是内部类中的testDemo方法");
        }
        public void testInnerDemo(){
            System.out.println("我是成员内部类的testInnerDemo方法:"+name);//这个name就是内部类的
            //如果想要访问外部类的name属性,应该这样写:
            System.out.println("我是成员内部类的方法:"+Demo.this.name);
            testDemo();
            Demo.this.testDemo();
        }
    }
}
    public static void main(String[] args) {
        //创建内部类的对象---调用内部类的方法
        Demo.InnerDemo innerDemo = new Demo().new InnerDemo();
        //调用内部类的方法
        innerDemo.testInnerDemo();
    }

输出结果:
在这里插入图片描述

内部类存在后 源代码进行编译 产生一个字节码 Demo$InnerDemo.class
我们可以看出,美元符号其实就是内部类命名的标志。
在这里插入图片描述

2.局部内部类

将一个类定义在方法/块里面,作为成员的内部结构,与临时的局部变量一个层次。
局部内部类是临时存在的,方法执行完,这个类的空间就被自动回收了。
局部内部类像是一个局部的变量一样,不能用public protected private及static
只能用abstract或final。
【小技巧】:在类中写一个空的main函数,让它去执行, 可以让该类立即被编译,生成.class文件。
在这里插入图片描述
局部内部类命名规则:
Demo$1InnerTestOneDemo
Demo$2InnerTestOneDemo
出现内部类重名以后,会有数字将它们区分开,1表示第1次出现的内部类,2表示第2次出现的内部类。

public class Demo {
    private String name = "这是正常类中的属性";
    public void testDemo(){
        System.out.println("这是正常类中的testDemo方法");
    }
    public void testDemoOne(){
        String s = "abc";
        //在方法中定义一个局部内部类
        class InnerTestOneDemo{
            //局部内部类使用的变量都需要加final来修饰
        }
    }
    {
        //在块中定义一个局部内部类,与方法中那个内部类重名了
        class InnerTestOneDemo{
            //局部内部类使用的变量都需要加final来修饰
        }
    }
}

*局部内部类使用的变量只能是final修饰,为什么?
因为局部内部类是类加载的时候就编译好了,编译好的.class文件是不能改变的,如果局部内部类中的变量不使用final修饰,让变量随意去改变,就会产生冲突。

*3.匿名内部类

成员匿名内部类
局部匿名内部类

不用匿名内部类,以前我们这样写:

public interface Test {
    public void test();
}
public class Son implements Test{
    @Override
    public void test() {
        //······
    }
}
    public static void main(String[] args) {
        Test t = new Son();
        t.test();
    }

有了匿名内部类以后,我们可以这样写:

public interface Test {
    public void test();
}
    public static void main(String[] args) {
        Test t = new Test(){
            public void test() {
                //······
            }
        };//分号不可省略
    }

new Test()后面的大括号里放的是匿名内部类的所有类成员。
通常接口或抽象类的具体子类这样写。
开发中为了省略一个类文件 , 上述写法比较常见。
匿名内部类很特殊, 只有类体, 没有类的( 修饰符 名字 继承 实现)。
不能用任何修饰符来修饰, 匿名内部类也没有构造方法。
应用:Swing 做一个按钮 ,绑定一个事件监听器

4.静态内部类

成员静态内部类
不需要外部类对象,通过正常的方式直接创建内部类即可!(前提是先导好包)
静态元素不能访问非静态成员(自己类和外部类的非静态成员都不行)。

public class Demo {

    //静态内部类
    public static class InnerDemoStatic{

    }
}
package innerclass;
import innerclass.Demo.InnerDemoStatic;
public class TestMain {
    public static void main(String[] args) {
        InnerDemoStatic innerStatic = new InnerDemoStatic();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章