阅读 102

浅谈java内部类(java中内部类的定义)

一、什么样的类属于内部类?

毫无疑问,居然是内部类,定义在类里面的类就是内部类。

public class Room {       class Student{//内部类        }   } 复制代码

内部类可以分为静态内部类(static修饰的类)和普通内部类。下面先讨论普通内部类:

(注意,以下所说的内部类都是指普通内部类)

1.内部类与外部类的关系: 对于普通内部类,实际上该类就类似于外部类的一个特殊成员,该内部类的创建必须依附于外部类,也就是说,必须先有外部类对象,才能创建内部类对象。这是因为内部类对象会隐式地连接到创建它的外部类对象上。并且内部类可以访问外部类的所有元素。创建时通过 .new来创建

public class Room {       private String book = "数据结构";       class Student{//内部类           public String getBook(){               return book;           }       }       public static void main(String[] args) {           Room r = new Room();           Student s = r.new Student();//不能有 Student s = new Student()来创建           System.out.println(s.getBook());       }   }  复制代码

注:如果要在内部类通过this关键字来引用外部类对象,则需要在这样引用 Room.this 。如果只是用this的话,引用的是内部类对象。

2.在方法和作用域内的内部类

(1).定义在方法内的内部类,我们称之为局部内部类:

public void get(){//只贴方法内的代码,其他代码省略       class Book{ //定义在方法内的内部类           String name = book;//book变量是外部类的成员属性       }   } 复制代码

显然,Book内只是方法get()的一部分,而不是外部类的一部分,所以,get()方法之外都不能访问Book。

(2).下面展示任何在任意作用域内嵌入一个内部类

public void get2(boolean b){       if(b){//在if语句作用域内定义内部类           class Book2{               String name = book;           }       }   }  复制代码

(3).内部类不能定义静态变量和静态方法

原因:类在初始化的过程中,是先初始化静态变量等的。也就是说,在编译是只要是定义为静态变量了,系统就会自动分配内存给它,但是内部类是依附与外部类的存在而存在的,也就是说只有外部类存在了,内部类才能存在,这就和编译时为静态变量分配内存产生了冲突。

3.匿名内部类

看下面一个程序

public class Animal {       public void run(){           System.out.println("我是一只不知名的动物");       }       public Animal getAnimal(){           return new Animal(){//返回匿名内部类               public void run(){                   System.out.println("我是一只小猫");               }           };       }       public static void main(String[] args) {           Animal a = new Animal();           Animal a1 = a.getAnimal();           a1.run();       }   } 复制代码

打印结果:我是一只小猫

在getAnimal()方法里,将返回值的生成与表示这个返回值的类定义结合在一起。另外,这个类是匿名的,没有名字。对于这种用法,看起来似乎你正要创建一个Animal的对象,实际上,创建的却是一个继承了Animal类的匿名对象,run()方法 是对父类方法的重写。

对于这种匿名内部类,使用的是默认构造器来生成Animal的,如果你的基类(也就是父类)需要一个有参数的构造器,该怎么办: 只需要把参数传递给基类的构造器即可。

public Animal getAnimal2(String name){       return new Animal(name){//直接把参数给它就行           public void run(){               System.out.println("我是一只" + name);           }       };   } 复制代码

以下来讨论静态内部类:

对于静态内部类,它与普通内部类不同。普通的内部类对象会隐式地保存了一个引用,指向创建它的外部类对象。然而,对于静态类来说,就不是这样了:

(1).要创建静态内部类,它并不需要其外部类的对象

public class Book {        static class Math{  }       public static void main(String[] args) {           Math m = new Math();//静态内部类的创建       }   } 复制代码

(2).静态内部类不能访问非静态的外部类对象

public class Book {       int B_price = 10;       static String B_name = "好书";              static class Math{           //int M_price = B_price;//不能访问           String M_name = B_name;       }   } 复制代码

对于为何不能访问非静态变量我是这样理解的:非静态量是属于类对象成员,而不是类成员,它的存在是依附于对象而不是类。静态内部类访问这个外部类成员的时候,这个成员还不存在,因为外部对象还没有被创建。故不能访问非静态成员。(当然,也可以从类加载的顺序等分析)。

(3).静态内部类还可以作为接口的一部分。

正常情况下,是不能在接口内部放置任何代码的,但是静态内部类可以作为接口的一部分。你放到接口中的任何类都自动地是public和static的。因为类是static的,只是将静态内部类置于接口的命名空间内,这并不会违反接口的规则:

public interface AA {       void get();       class BB implements AA{           @Override           public void get() {               System.out.println("哈哈");              }          }   }  复制代码

二、为啥需要内部类?

1.对于抽象类,我们都知道只能被单继承,如果一个类想要继承多个抽象类,那只能使用内部类才能实现多重继承(即定义几个内部类,每个内部类分担继承一个)。

2.内部类的使用,对一个类来说,提供了更好的封装。例如要生产一辆车,我们可以假设老板是外部类,负责组装车部件的团队是内部类。那么你想要修改车里面的部件时,不仅仅是通过老板就可以直接做出修改了,还得通过负责装车部件的团队。也就是说,外部类的有些属性成员,只要通过内部类才能修改,这样子设计,会更具合理性。

3.内部类可以有多个实例,每个实例都有自己的状态信息,并且与其外部类对象的信息相互独立。

4.在单个外部类中,可以让多个内部类以不同的方式实现同一个接口,或继承同一个类。

三、内部类可以被覆盖吗?

看下面一个例子

打印结果: Eat Eat.Apple 复制代码

从输出的情况可以看出,内部类并没有被覆盖。也就是说,两个内部类并没有啥关系,是相互独立的。


作者:帅地
链接:https://juejin.cn/post/6844903606223634439


文章分类
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐