本文原创首发CSDN,本文链接 https://blog.csdn.net/qq_41464123/article/details/107480664 ,作者博客https://blog.csdn.net/qq_41464123 ,转载请带上本链接,谢谢配合。
零、为什么要写内部类?
之前在学习Android百度地图的时候,发现一个Activity中居然有两个嵌套的类(Class),成功引起了我的注意,于是最近在暑假系统了学习了Java中的四种内部类。
最初在大二入门Java的时候,我就了解过Java的匿名类和内部类,那时候觉得这些都是理论性的东西,实际开发不一定能用到,于是就淡化了。直到最近,发现Java的内部类机制在实际开发中用处还是不小的,于是系统的学习了内部类,并写下了这篇总结。
一 、类
1.1 基础类
类的概念、访问权限修饰符,我已经在《学习Java的你,真的会面向对象编程吗?》详细讲解了。
类是什么?类是静态的模板,规定了 将该类实例化的对象 的共性。
1. public class People { 2. 3. String userName; 4. int userAge; 5. 6. void say() { 7. System.out.println("The people " + this.userName + " is "+ this.userAge + " years old!"); 8. } 9. }
看,这就是一个 People 类,他有成员变量 userName、userAge,还有成员方法say();
1.2 封装类
如果结合上Java的封装原则,那么,就需要为成员变量、成员方法加上访问权限修饰符,代码就变成了这个样子:
1. public class People { 2. 3. private String userName; 4. private int userAge; 5. 6. public void say() { 7. System.out.println("The people " + this.userName + " is "+ this.userAge + " years old!"); 8. } 9. 10. public String getUserName() { 11. return userName; 12. } 13. public void setUserName(String userName) { 14. this.userName = userName; 15. } 16. public int getUserAge() { 17. return userAge; 18. } 19. public void setUserAge(int userAge) { 20. this.userAge = userAge; 21. } 22. }
从程序功能上来说,前后两段代码的功能是一致的,但是从Java语言开发规范角度来讲,每一个实体类都必须满足封装原则,简单来讲,实体类的成员变量必须为私有类型,并且提供 set 和 get 方法让外部获取、修改变量。
可以说,上面这段程序才是真正意义上的Java实体类Bean。
二、内部类
我的理解:内部类就是类中类,依附于普通类中,可以间接实现Java类的多继承。
内部类是指在一个外部类的内部再定义一个类,内部类作为外部类的一个成员,是依附于外部类存在的。
内部类可以是静态的,通常用 protected 或者 private 关键字修饰,外部类只能使用public或者系统默认权限。
如果你对Java的访问权限不熟悉,可以看一下我这篇文章《一文搞懂Java的 构造方法 和 访问权限》
内部类主要有四种,分别是成员内部类、方法内部类、静态内部类、匿名内部类。(图片来源于网络,侵删)
2.1 成员内部类
成员内部类,顾名思义就是内部类作为成员存在于类中,和成员变量、成员方法同级。
比如下面这个 People 类,包含了一个内部类 Book,该类和成员变量 userName 、userAge 同级。
Book内部类,也可以拥有自己的成员变量、成员方法,以及自身的构造方法
1. public class People { 2. 3. class Book{ 4. String bookName; 5. 6. Book(String bookName){ 7. this.bookName = bookName; 8. } 9. 10. void open() { 11. System.out.println("The " + this.bookName + " was opened!"); 12. } 13. } 14. }
我们如果要实例化这个成员内部类,就必须采用
外部类.内部类 内部类对象 = new 外部类().new 内部类();
实际代码如下:
1. public class Main { 2. 3. public static void main(String[] args) { 4. People.Book book = new People().new Book("Java程序设计"); 5. book.open(); 6. } 7. }
运行效果如下,也就是调用了内部类 Book 的 open() 方法,输出这样一句话。
2.2 静态内部类
在讲解静态内部类之前,先讲解一下静态,也就是static关键字。
static是静态的意思。在Java语言中,static关键字修饰的成员是可以被所有对象共享的。
如果某个类加了static关键字,则直接可以使用类名直接访问。
将2.1小节的People类中的 Book子类,加上一个 static关键字 修饰
1. static class Book{ 2. String bookName; 3. 4. Book(String bookName){ 5. this.bookName = bookName; 6. } 7. 8. void open() { 9. System.out.println("The " + this.bookName + " was opened!"); 10. } 11. }
那么外部就直接可以使用类名进行实例化操作,就像一个普通实例类一样,如下面代码所示:
1. import cn.zwz.People.Book; 2. 3. public class Main { 4. 5. public static void main(String[] args) { 6. Book book = new Book("Java程序设计"); 7. book.open(); 8. } 9. }
我们可以得到和 2.1小节所讲的一致的效果。
方法内部类是指在Java方法中定义的类。
我们在原有的 People 类中,定义一个say()方法,在该方法中定义一个 Issue 内部类。
在 Issue 内部类中,定义一个方法 speakIsser(),内容是输出话题的名称。
1. public class People { 2. 3. public void say(String issue) { 4. class Issue { 5. public void speakIsser() { 6. System.out.println("My issues is " + issue); 7. } 8. } 9. new Issue().speakIsser(); 10. } 11. }
接着编写测试方法,实例化一个 People 对象,并调用 people 的 say() 方法
1. public class Main { 2. 3. public static void main(String[] args) { 4. People people = new People(); 5. people.say("Hello ZWZ!"); 6. } 7. }
运行结果显示,people 的 say() 方法,调用了 Issue内部类中的 speakIsser()方法,输出了这句话。
2.4匿名内部类
我们对第三小节的程序稍加修改
1. 定义一个Issue接口,或者普通类。
2. 在 People 类的 say()方法中,new 出来一个 Issue 对象,实现 speakIsser() 抽象方法的具体实现。
3. 在Issue对象的后面调用speakIsser()方法。
代码如下所示:
1. interface Issue{ 2. public void speakIsser(); 3. } 4. public class People { 5. 6. public void say(String issue) { 7. new Issue() { 8. public void speakIsser() { 9. System.out.println("My issues is " + issue); 10. } 11. }.speakIsser(); 12. } 13. }
测试方法程序,同第三小节的方法内部类,不做修改
1. public class Main { 2. 3. public static void main(String[] args) { 4. People people = new People(); 5. people.say("Hello ZWZ!"); 6. } 7. }
运行结果如下图所示,即效果同第三小节的方法内部类。
匿名内部类是一种特殊的内部类,这种类没有名字,通过new关键字直接创建某一个类的匿名子类的对象来使用。
以下情况需要用到匿名类:
- 只用到类的一个实例。
- 类在定义后马上用到。
- 类非常小,通常5行代码之内。
- 给类命名不会导致代码更容易被理解。
但是需要注意:匿名内部类不能定义构造方法,并且功能上会受到很大的限制,如果不是很有必要,尽量不要去使用。
三、总结
以上就是Java四种内部类的常见用法。
1.成员内部类,就是内部类作为一个成员,存在于类中。
实例化方法: 外部类.内部类 内部类对象 = new 外部类().new 内部类();
2.静态内部类,在成员内部类的基础上,多了一个static关键字,是静态的类,所有的对象都可以直接通过类名调用。
实例化方法: 内部类 内部类对象 = new new 内部类();
3.方法内部类,在类的方法中,定义内部类。
实例化方法: new 内部类().内部类方法(); 注意只能在当前方法中实例化。
4.匿名内部类,直接new一个没有名字的类,并且直接调用其中的方法。
实例化方法: new 内部类(){ ...... }.内部类中的方法();
参考文献:《Java语言面向对象程序设计(第二版)》 清华大学出版社