内部类的概念 | |
内部类的分类 | 成员内部类 |
静态内部类 | |
局部内部类 | |
匿名内部类 |
内部类的概念
什么是内部类:
- 定义在类内部的类
public class Test {
class innerClass{ //内部类
public void method() {
System.out.println("innerClass");
}
}
}
返回顶层目录
内部类的分类
成员内部类:
- 定义在类内部的非静态类,就是成员内部类。
实例内部类是 属于对象的内部类,是 不属于类的,不使用static修饰的内部类
- 意思就是把这玩意儿看成是一个对象,别把他当类看
内部类 可以 访问 外部类 当中的成员;
外部类 不能 直接访问 内部类 当中的成员
- 意思是 我们要把‘实例内部类’看作对象,而不是类,因此内部类中的成员变量不能使用static修饰,因为static是属于‘类’的 字段和方法,而实例内部类是对象。如果强行写上,编译器会报错。
内部类 可以 访问 外部类 当中的成员
外部类 不能 直接访问 内部类 当中的成员
- 意思是 我们要把‘实例内部类’看作对象,而不是类,因此内部类中的成员变量不能使用static修饰,因为static是属于‘类’的 字段和方法,而实例内部类是对象。如果强行写上,编译器会报错。
package test2;
class Outter {
String name = "OutterName";
class InnerClass{ //内部类
// static int a; //不能为static
// final int a;
String name = "Chenny";
void testFuc() {
String name = "testName";
System.out.println(name); //方法内的name
System.out.println(this.name); //内部类中的name
System.out.println(Outter.this.name); //外部类中的name
}
}
}
public class Test{
public static void main(String[] args) {
Outter o = new Outter();
System.out.println(o.name);
// InnerClass in = new InnerClass();
Outter.InnerClass in = o.new InnerClass();
in.testFuc();
}
}
返回顶层目录
静态内部类
静态内部类:
- 静态内部类是 在内部类前面加上static,静态内部类是 不需要创建外部对象。
Outter.InnerClass in = new Outter.InnerClass();
在静态内部类当中, 没有外部类引用
- 意思是他在堆中开辟的空间 里面没有存放外部类的地址
静态内部类,是可以访问外部类的静态成员
- 但是不能直接访问外部类中的非静态成员变量
- 如果想要访问外部类中的非静态成员变量 可以new一个外部类出来:new Outer().age
访问静态内部类当中的静态成员:Outter.Inner.color
- 不需要new内部类,直接把内部类当对象用
静态内部类当中不仅可以定义静态成员也可以定义非静态成员
class Outter {
int a = 10;
static int b = 11;
final int c = 12;
static class InnerClass{
String name = "Chenny";
void testFuc() {
String name = "testName";
System.out.println(name); //方法内的name
System.out.println(this.name); //内部类中的name
// System.out.println(a); //Error
System.out.println("b = " + b);
// System.out.println("c = " + c); //Error
}
}
}
public class Test{
public static void main(String[] args) {
Outter.InnerClass in = new Outter.InnerClass();
in.testFuc();
}
}
返回顶层目录
局部内部类
局部内部类:
- 定义在方法中的内部类。
- 不能使用一些修饰符public private…
- 局部内部类只能定义在方法当中使用
- 局部内部类当中是不能包含静态变量
因为局部内部类是‘属于方法的’,而static是‘属于类的’,两者相矛盾
局部内部类当中可以包含局部变量,使用的局部变量的本质是final变量
在方法中new出局部类,会在堆中开辟空间,若局部内部类使用了栈中该方法栈帧的成员变量,一旦方法栈帧出栈,堆中的成员变量就无法找到指向的元素,会空指针异常
为了避免这种情况,只能将方法中的成员变量设为static或final,但是static又不能设,所以只能设置为final
class People {
public People() {
}
}
class Man {
public Man() {
}
public People getWoman() {
class Woman extends People { // 局部内部类
int age = 0;
}
return new Woman();
}
}
返回顶层目录
匿名内部类
匿名内部类:
- 它连名字都没有 所以也没有构造器 一个文件对应一个类
- 只使用一次的时候,就使用匿名内部类
- 匿名内部类必须得要有父类,或者是实现了接口
一般使用匿名内部类的场景是,要继承或实现的接口只有一个抽象方法,比如添加一个监听器:
返回顶层目录
实例一
public class Test {
public void click() {
// 匿名内部类,实现的是ActionListener接口
new ActionListener() {
public void onAction() {
System.out.println("click action...");
}
}.onAction();
}
// 匿名内部类必须继承或实现一个已有的接口
public interface ActionListener {
public void onAction();
}
public static void main(String[] args) {
Test button = new Test();
button.click();
}
}
示例二
abstract class Person {
public abstract void eat();
}
class Child extends Person {
public void eat() {
System.out.println("eat something");
}
}
public class Test {
public static void main(String[] args) {
Person p = new Child();
p.eat();
}
}
示例三
abstract class Person {
public abstract void eat();
}
public class Test {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
示例四
interface Person {
public void eat();
}
public class Test {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("eat something");
}
};
p.eat();
}
}
示例五
public class Test {
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();
}
}
示例六
public class Test {
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();
}
}