一. 内部类 (成员内部类,局部内部类,静态内部类,匿名内部类)
1. 内部类含义:
在类的内部也可以定义另一个类。如果在类Outer的内部再定义一个类Inner,此时Inner就称为内部类,而Outer则称为外部类。 当内部类声明成public或private等时,对其访问的限制与成员变量和成员方法完全相同。 内部类的定义格式 标识符 class 外部类的名称{ //外部类的成员 标识符 class 内部类的名称{ //内部类的成员 } }
// 2. 内部类可分为:
成员内部类,局部内部类,静态内部类,匿名内部类
3. 内部类跟普通类是一样的,普通的类能干什么,内部也可以干什么,比如:继承 ,实现接口 ,可以帮助外部类实现多继承的功能,
二. 成员内部类
(1)
01. 成员内部类中,不能定义静态的属性 例如:
public static int innerStaticField = 1;
02.可以访问外部类的的私有属性
03.可以访问外部类的静态属性
04.
内部类访问外部类属性的方法 Outer.this.属性 例如:S
ystem.out.println("a:" + MemberOuter.this.a); //内部类访问外部类属性方法;
05.
(2)成员内部类的运用场景
1. 通过内部类可以实现类的多继承
2. 如果外部类,是一个逻辑非常复杂的一个,需要操作好多属性或方法,这个时候,可以将功能进行才分让某个或者多个内部类,帮忙处理
案例:
package com.qianfeng.demo3;
//外部类Circle
public class
Circle {
private int radius;
//把画圆的动作单独抽成一个内部类,它值负责画圆这个动作
class
Draw{
private int radius;
public Draw(int radius){
this.radius = radius;
}
public void draw(){
System.out.println("真实画圆的逻辑....");
System.out.println("内部类的画圆..." + radius);
}
}
//准备画圆所需的环境,获取其他可变的参数
//在设置后对象的参数,调用内部类对象进行有差别的画圆(可变参数决定)
public void draw(int radius){
System.out.println("准备画圆所需要的环境,其他的东东....比如:画一个白色圆圈");
Draw draw = new Draw(radius);
draw.draw();
System.out.println("画圆..." + radius);
}
public void draw2(int radius){
System.out.println("准备画圆所需要的环境,其他的东东....比如:画一个黑色圆圈");
Draw draw = new Draw(radius);
draw.draw();
System.out.println("画圆..." + radius);
}
public static void main(String[] args) {
Circle circle = new Circle();
circle.draw(1);
}
}
三. 局部内部类
局部内部类也叫区域内嵌类,局部内部类与成员内部类类似,不过,区域内嵌类是定义在一个方法中的内嵌类,
所以类的作用范围仅限于该方法中,而类生成的对象也只能在该方法中使用,另外,由于是在方法中定义,
因此区域内嵌类不能加上 private , protected , public 中的任何一个修饰符,不能包含静态成员。
局部内部类示例:
四. 静态内部类
1. 在静态内部类中,非静态方法可以访问外部类静态属性,但不能访问非静态属性
2. 可以访问内部类定义的静态属性,也可以访问非静态属性
3. 静态方法,只能访问静态属性或方法,不能访问非静态方法或属性,不过内部类和外部类
五. 匿名内部类
//匿名内部类创建对象方式:等价于InterInner interImpl = new InterInnerImpl();
//不一样的地方是:没有类名
//1、继承某一个类
//2、实现某一个接口
//3、在任何地方都可以创建匿名内部类
匿名内部类也就是没有名字的内部类
正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
实例1:不使用匿名内部类来实现抽象方法
abstract
class
Person {
public
abstract
void
eat();
}
class
Child
extends
Person {
public
void
eat() {
System.out.println(
"eat something"
);
}
}
public
class
Demo {
public
static
void
main(String[] args) {
Person p =
new
Child();
p.eat();
}
}
运行结果:eat something
可以看到,我们用Child继承了Person类,然后实现了Child的一个实例,将其向上转型为Person类的引用
但是,如果此处的Child类只使用一次,那么将其编写为独立的一个类岂不是很麻烦?
这个时候就引入了匿名内部类
实例2:匿名内部类的基本实现
abstract
class
Person {
public
abstract
void
eat();
}
public
class
Demo {
public
static
void
main(String[] args) {
Person p =
new
Person() {
public
void
eat() {
System.out.println(
"eat something"
);
}
};
p.eat();
}
}
运行结果:eat something
可以看到,我们直接将抽象类Person中的方法在大括号中实现了
这样便可以省略一个类的书写
并且,匿名内部类还能用于接口上
实例3:在接口上使用匿名内部类
interface
Person {
public
void
eat();
}
public
class
Demo {
public
static
void
main(String[] args) {
Person p =
new
Person() {
public
void
eat() {
System.out.println(
"eat something"
);
}
};
p.eat();
}
}
运行结果:eat something
由上面的例子可以看出,只要一个类是抽象的或是一个接口,那么其子类中的方法都可以使用匿名内部类来实现
最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口
实例4:Thread类的匿名内部类实现
public
class
Demo {
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
实例5:Runnable接口的匿名内部类实现
public
class
Demo {
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