提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


内部类

  • 前言
  • 一、成员内部类
  • 二、静态内部类
  • 三、方法内部类
  • 四、匿名内部类



前言

内部类在Java的学习与应用中有着很大的作用,同时也起到了一定的封装作用。

一、成员内部类

内部类的使用方法:

a.内部类可以互相访问private属性

因为内部类隐藏了外部类的对象)所以在输出                val时,实际上是Test.this.val.

     (2) 外部类必须通过内部类的对象来访问内部类的元素和方法,下列代码中student可以调用fun          ()方法和private属性的age。

public class Test {
    private int val=12;
    private String str;
     //-----------------------
      class Student{
        private int age;
        private String name;

        public Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
        public void fun(){
            System.out.println(val);
        }
    }
    //-------------------------
    public void fun2(){
        Student student=new Student(12,"张三");
        student.fun();
        System.out.println(student.age);
    }
    public static void main(String[] args) {
        Test test=new Test();
        test.fun2();

    }
}

b.成员内部类的对象创建:

   (1)外部类内部创建(此时的内部指的是Test这个类里面):

            上述代码中fun2()方法,就创建了student对象。

   (2)外部类的外部创建(此时就是在Test这个类的外面):

public class Test1 {
    public static void main(String[] args) {
        Test.Student student=new Test().new Student(45,"李四");
        //输出结果是12
       student.fun();
    }
}

注意:对此由于内部类的创建必须依赖于外部类,所以一定要使用Test这个外部类来一步步产生  student对象。由于Student这个成员内部类在Test中是包访问权限,Test1与Student在同一个包下,因此Test1是可以看到的,如果将Studnt这个类加上private,此时上述代码就不可实现了,其实和成员方法有着很大的相似。 

c.成员内部类其它:

(1)成员内部类不可以定义静态变量,可以访问外部类的成员域、静态域:

        对于不可以定义静态变量我自己的理解:对于成员内部类(类比成员变量),必须依赖于外部            类,若定义了静态变量,则没有外部类对象也可以访问了。所以就会产生矛盾!

不可以直接在静态方法中使用成员内部类:

public  static void fun2(){
        Student student=new Student(12,"张三");
        student.fun();
        System.out.println(student.age);
    }

此时上述代码是错误的:因为静态方法不需要产生外部类对象就可以通过类调用,而成员内部类必须依赖于外部类对象,所以是不可以的!

        解决方法:可以在fun2()方法内部,通过外部类产生内部类对象。

public  static void fun2(){
       Test.Student student=new Test().new Student(21,"阿娇");
       student.fun();
        System.out.println(student.age);
    }

好了到这里,这个问题已经变得很清楚了!!!

   

          

二、静态内部类

 静态内部类:定义在类中,使用static修饰的内部类。

这里只需要在内部类加上static修饰就OK了!

public class Test {
    private  int val=12;
    private String str;
     //-----------------------
     static class Student{
        private int age;
        private  String name;

        public Student(int age, String name) {
            this.age = age;
            this.name = name;
        }
        public void fun(){
            //此时就不可以直接访问外部类的成员变量val,当然如果val被static修饰就可以
            //此时就要产生一个外部类对象
            System.out.println(new Test().val);
        }
    }
    //-------------------------
    //此时如果是public static void fun2(),也可以直接使内部类。
    public void fun2(){
         Student student =new Student(45,"阿花");
         student.fun();

    }
    public static void main(String[] args) {
        Test test=new Test();
        test.fun2();
    }
}

所以只要那个成员内部类懂了,这个静态方法大同小异! 但还有以下值得注意的:

(1)静态内部类可以拥有成员变量。

 (2)静态内部不可以直接外部类的成员变量,但可以new出来一个外部类的对象访问,上述代码fun      (),方法中就体现出来了。

 (3)在外部类的外部创建内部类的对象:

public class Test1 {
    public static void main(String[] args) {
        Test.Student student=new Test.Student(45,"小花");
        student.fun();
    }
    
}

此时相对于 成员内部类在外部类的外部创建内部类对象,有差点差别,因为静态内部类不需要产生对象,只需要使用类名称即可。

三、方法内部类

定义:定义在方法内部的类,不允许使用任何访问修饰符,对外部完全隐藏(出了这个方法就没了)

public class Test {
    private int age = 10;
    public void fun(int num) {
        // 方法内部类,不能出现任何访问修饰符和static
        class Inner {
            public void test() {
                System.out.println(age);
                System.out.println(num);
            }
        }
        // 此时Inner使用num这个变量,num就变为了隐式的final,值不能修改
        Inner inner = new Inner();
        inner.test();
    }

    public static void main(String[] args) {
        Test test=new Test();
        Test.fun(10);
    }
}

注意:方法的内部类若使用了方法的形参,则该形参为隐式的声明,则该参数不可被修改。

四 、匿名内部类

定义:是方法内部类的特殊版本,直接不写类名称;遵从方内部类的所有要求,匿名内部类会默认继承一个类或接口。 

public class Test {
    public static void fun(IMessage msg) {
        msg.printMsg();
    }
    public static void main(String[] args) {
        fun(new IMessage() {
            // 这就是一个匿名内部类
            // 等同于创建了一个类实现了Imessage接口,创建该类的对象
            @Override
            public void printMsg() {
                System.out.println("匿名内部类的用法");
            }
        });
//       上面的使用就等同于下面两行
//        IMessage msg = new IMessageImpl();
//        fun(msg);
    }
}
interface IMessage {
    void printMsg();
}
class IMessageImpl implements IMessage {
    @Override
    public void printMsg() {
        System.out.println("普通用法");
    }
}

这个是自己写的接口,自己实现的,上面显示了普通用法和匿名用法。通过比较很容易发现里面的关系。

但我们平时做题时,也经常会用到JDK自带的各种接口,例如comparator接口,也叫比较器。

Queue<Freq> queue=new PriorityQueue<>(new Comparator<Freq>() {
            @Override
            public int compare(Freq o1, Freq o2) {
                return o2.times-o1.times;
            }
        });

这个就是采用匿名内部类实现了一个基于最大堆的优先级。


总结

这是我第一次尝试些博客,可能对排版啥的有些欠缺,希望大家伙理解哈。接下来那我一定还会将其他的一些知识,以一个比较容易理解的方式,呈现给大家,希望大家可以喜欢哦。滴  滴滴~~