Java学习笔记之内部类方面

内部类

一个类中包含另一个类

  • 成员内部类
  • 局部内部类(匿名内部类)

成员内部类

定义代码:

public class DemoInerClass { //外部类

    class NewClass{//成员内部类
        public void newMethod(){
            System.out.println("我是内部类!");
            System.out.println("我叫"+name+"多少岁"+age);//可以访问外部类中的成员变量
        }
    }
    private String name;
    private int age; 
    //外部类方法
    public void method(){
        System.out.println("我是外部类方法");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

使用代码:

间接使用

在外部类的方法当中使用内部类,然后main使用外部类的方法。

 	//外部类方法,再外部类的方法中创建内部类对象,再调用内部类方法
    public void method(){
        System.out.println("我是外部类方法");
        //间接使用内部类的方法
        NewClass newClass = new NewClass();
        newClass.newMethod();
    }
    //main方法所在类
    public class Demo {
    public static void main(String[] args) {
        DemoInerClass demoInerClass = new DemoInerClass();
        demoInerClass.setAge(10);
        demoInerClass.setName("小花");
        demoInerClass.method();//调用外部类方法间接使用内部类方法
    }
}

直接使用

外部类.内部类 对象名 = new 外部类().new NewClass();
对象名不能访问外部类的成员变量和方法,只能访问内部类的成员变量和方法

public class Demo {
    public static void main(String[] args) {
        DemoInerClass.NewClass demo = new DemoInerClass().new NewClass();
        DemoInerClass demoOne = new DemoInerClass();
        demo.newMethod();
    }
}

内部类未编译时:
在这里插入图片描述
内部类编译后的情况:
在这里插入图片描述

变量名重名问题

代码解释如下:

public class Outer {
    int num = 10;//外部类成员变量
    public class Inner{
        int num = 20;//内部类成员变量
        public void method()
        {
            int num = 30;//内部类方法的局部变量
            System.out.println(num);//30
            System.out.println(this.num);//20
            System.out.println(Outer.this.num);//10
        }
    }
}

public class OuterDemo {
    public static void main(String[] args) {
        Outer.Inner obj = new Outer().new Inner();//注意格式
        obj.method();
    }
}

结果:

"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=62487:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo09.OuterDemo
30
20
10

局部内部类

一个类定义在方法内部,只有当前的方法可以用它,出了这个方法就不能用了。
代码解释:

public class Out {//外部类
    public void outMethod()
    {
        class In{//局部内部类
            int num = 10;
            public void inMethod()
            {
                System.out.println(num);//10
            }
        }
        In in = new In();
        in.inMethod();
    }
}

public class DenoOut {
    public static void main(String[] args) {
        Out out = new Out();
        out.outMethod();
    }
}

结果:

"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=62718:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo08.DenoOut
10

Process finished with exit code 0

类的修饰符

用什么修饰?
外部类 public/default
成员内部类 public/default/protected/private
局部内部类 什么都不写

注意事项

局部内部类访问所在方法的局部变量,这个变量必须是有效final的(从Java 8+开始只要局部变量事实不变,可以省略final)所谓有效final:值不能变
具体原因:生命周期(谁活得久的问题)
1、new出来的对象再堆内存中
2、局部变量是跟着方法走的,在栈内存中
3、方法运行之后立刻出栈,局部变量立刻消失
4、new出来的对象会持续存在,直到垃圾回收

public class Out {//外部类
    public void outMethod()
    {
        int num = 10;
        final int one = 20;//Java 8+之后可省略final
        //num = 30;//此时如果再给num赋值,则报错。
        class In{//局部内部类
            public void inMethod()
            {
                System.out.println(num);//10
                System.out.println(one);//20
            }
        }
        In in = new In();
        in.inMethod();
    }
}

匿名内部类(没有名字)

如果接口的实现类(或者父类的子类)只需使用唯一的一次,那么这种情况下就可以省略掉该类的定义,改为使用【匿名内部类】

有如下接口:

public interface NewInter {
    void method();
}

普通实现方式:使用类NewInterImpl去实现接口NewInter–>在main方法中调用。代码如下:

public class NewInterImpl implements NewInter {
    @Override
    public void method() {
        System.out.println("实现接口的抽象方法!");
    }
}
public class New {
    public static void main(String[] args) {
        NewInter newInterImpl = new NewInterImpl();
        newInterImpl.method();
        //多态实现
        NewInter obj = new NewInterImpl();
        obj.method();
    }
}
"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=60960:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo10.New
实现接口的抽象方法!
实现接口的抽象方法!

Process finished with exit code 0

利用匿名内部类实现:则可省略接口的实现类。

public class New {
    public static void main(String[] args) {
        NewInter obg = new NewInter() {
            @Override
            public void method() {
                System.out.println("实现接口的抽象方法!");
            }
        };
        obg.method();
    }
}
"E:\JAVA\IntelliJ IDEA 2019.3.2\jbr\bin\java.exe" "-javaagent:E:\JAVA\IntelliJ IDEA 2019.3.2\lib\idea_rt.jar=60970:E:\JAVA\IntelliJ IDEA 2019.3.2\bin" -Dfile.encoding=UTF-8 -classpath E:\JAVA\project\day06-code\out\production\day06-code com.lg.demo10.New
实现接口的抽象方法!

Process finished with exit code 0

对匿名内部类格式的解析

new 接口名称(){......}

1.new 代表创建对象的动作。
2.接口名称就是匿名内部类要实现哪个接口。
3.{…}匿名内部类的真正内容。

注意事项
1.匿名内部类,在【创建对象】的时候,只能使用唯一 次。如果希望多次创建对象,而且类的内容一样的话,那么就必须使用单独定义的实现类了。
2.匿名对象,在【调用方法】的时候,只能调用唯一次。如果希望同一个对象,调用多次方法,那么必须给对象起个名字。
3.匿名内部类是省略了【实现类/子类名称】,但是匿名对象是省略了【对象名称】

**强调:匿名内部类和匿名对象不是一回事! ! ! **

即匿名对象又是匿名内部类:

  new NewInter() {
            @Override
            public void method() {
                System.out.println("实现接口的抽象方法!");
            }
        }.method();
发布了22 篇原创文章 · 获赞 0 · 访问量 437

猜你喜欢

转载自blog.csdn.net/ENDEAVOR__/article/details/104940956