正文:
“内部类"简单说就是在一个类的内部又定义了一个类,这个定义在已知类内部的类就称为"内部类”。由于是定义在一个已知类的内部,所以它既具备一个累的特征,又在很多方面的表现和普通类有不同。
下面,我打算从三个方面来讲解内部类的使用,并验证内部类的概念:
一、普通类中定义内部类(不常见)
"内部类"虽然有不同于普通类的特性,但是它终归是类,是类就必须能创建对象并调用其中的方法来执行功能,这是定义类的意义。
我们来写一个例子,看看内部类的属性是怎么调用的:
public class innerTest {
int num = 100;
private class inner{
int num = 200;
public void print(){
int num = 500;
System.out.println(num); //方法内属性
System.out.println(this.num); //内部类属性
System.out.println(innerTest.this.num); //外部类属性
}
}
public static void main(String[] args) {
innerTest innerT = new innerTest();
innerTest.inner inner = inner.new inner();
inner .print();
System.out.println(innerT.num + inner .num); //调用内部类的num属性
}
}
// 输出结果分别为:500,200,100,300
内部类的特性:
- "内部类"中可以定义属性,这些属性可以被其所在的普通类访问,甚至是可以访问"内部类"的私有属性(private)。当这些属性出现重名情况时,需要进行访问限定修饰;
- 普通类的内部可以定义多个内部类和接口,并且具备继承、实现的关系;
- 用static关键字,升级为顶级内部类,具备和普通类相同的特征,一模一样;
- "内部类"可以再进一步进行嵌套,构建对象时则需要按层进行构建。
二、方法中定义内部类(了解)
方法中也可以定义"内部类",方法中的"内部类"在事件处理中比较常见,在jdk1.8版本之前如果"内部类"需要访问其所在方法中的局部属性,则这个局部属性需要用final修饰。jdk1.8版本就不需要进行这个操作了,但是其本质还是final的,是不能对其进行修改的,看一个例子:
public class innerTest {
public void innerMethod(){
int num = 100;
class innerClass{
public void print(){
System.out.println("可以访问方法的属性,但不可以修改:"+num);
}
}
innerClass inner = new innerClass();
inner.print();
}
public static void main(String[] args) {
innerTest inner = new innerTest();
inner.innerMethod();
}
}
//输出结果为:可以访问方法的属性,但不可以修改:100
三、匿名内部类(常用)
在实际开发中,我们通常用“匿名内部类”的方式来代替上面在方法中定义内部类的情况,它的写法简化很多,但意义是一样的,下面我们介绍一下:
顾名思义,匿名内部类也就是没有名字的内部类。正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码的编写。
在使用匿名内部类时,要记住以下几个原则:
- 匿名内部类不能有构造方法;
- 匿名内部类不能定义任何静态成员、方法和类;
- 匿名内部类不能是public,protected,private,static;
- 只能创建匿名内部类的一个实例;
- 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类;
- 因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
下面我讲述一下“匿名内部类”存在的意义:
abstract class Person {
public abstract void speak();
}
class Child extends Person {
public void speak() {
System.out.println(“代码很冗余的说!!”);
}
}
public class Demo {
public static void main(String[] args) {
Person p =new Child();
p.speak();
}
}
可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用。但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?
这个时候就引入了匿名内部类,它存在的意义就是为了简化冗余的代码,如下:
abstract class Person {
public abstract void speak();
}
public class Demo {
public static void main(String[] args) {
Person p =new Person() {
public void speak() {
System.out.println(“代码是不是清爽了很多??”);
}
};
p.speak();
}
}
噔噔噔噔~~ 是不是很清爽了,我们直接将抽象类Person中的方法在大括号中实现了!
其实,只要是抽象类或是接口,那么其子类中的方法都可以使用匿名内部类来实现,最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口。
常用的匿名内部类实现:
- Thread类的匿名内部类实现
public class ThreadDemo {
public static void main(String[] args) {
Thread t =new Thread() {
public void run() {
for(int i = 1; i <= 5; i++) {
System.out.print(i +",");
}
}
};
t.start();
}
}
//输出结果:1,2,3,4,5,
- Runnable接口的匿名内部类实现
public class RunnableDemo {
public static void main(String[] args) {
Runnable r =new Runnable() {
public void run() {
for(int i = 1; i <= 5; i++) {
System.out.print(i +" ");
}
}
};
Thread t =new Thread(r);
t.start();
}
}
//输出结果:1,2,3,4,5,
小结
- "内部类"中可以定义属性,这些属性可以被其所在的普通类访问。当这些属性出现重名情况时,需要进行访问限定修饰;
- 用static关键字,升级为顶级内部类,具备和普通类相同的特征,一模一样;
- 方法中定义的内部类,只能访问方法中定义的final类型的局部变量;
- 使用匿名内部类,必须继承一个父类或实现一个接口,这点很重要!!
特此声明:本文章为转载文章,仅作为学习参考,便于日后温习为目的,恭请少数关注的博友,直接点击转载博文的标题,链入原文,也算尊重原文作者的劳动。
本文链接:https://blog.csdn.net/weixin_44259720/article/details/87918110