引言:
Java中的内部类。当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部完整的结构有只为外部事物提高服务,那么这个内部完整的结构最好使用内部类。
java 中允许一个类的定义位于另一个类的内部,前者称为内部类,后者称为外部类。Inner class一般在定义它的类或语句块之内使用,在外部引用它是必须给出完整的名称。Inner class的名称不能与包含它的外部类类名相同。
Java中允许将一个类A声明在另一个类B中,则类A就是内部类,类B称为外部类
分类
- 成员内部类(static成员内部类和非static成员内部类)
- 局部内部类(方法内、代码块内、构造器内)
- 匿名内部类
成员内部类:
- 一方面,作为外部类的成员:
- 调用外部类的结构
- 可以被static修饰
- 可以被4种不同的权限修饰
- 另一方面,作为一个类:
- 类内可以定义属性、方法、构造器等
- 可以被final修饰,表示此类不能被继承。言外之意,不使用final,就可以被继承
- 可以被abstract修饰
- 内部类的结构
//外部内
class Person {
String name;
int age;
public void eat() {
System.out.println("人,吃饭");
}
//静态成员内部类
static class Dog{
String name;
int age;
public void show() {
System.out.println("卡拉是条狗");
//eat();//报错,静态结构中不能调用非静态的属性、方法
}
}
//非静态成员内部类
class Bird {
//属性
String name;
//方法
public void sing() {
System.out.println("我是一只小小鸟");
//内部类中调用外部内的属性和方法
Person.this.age = 2;
eat();//Person.this.eat();
}
//构造器
public Bird() {}
}
{
//局部内部类
class BB {}
}
public Person() {
//局部内部类
class CC {}
}
public void method() {
//局部内部类
class AA {}
}
//成员内部类
private class A1{}
class A2{}
protected class A3{}
public class A4{}
final class A5{}
static class A6{}
static final class A7{}
abstract class A8{}
//内部接口
private interface B1{}
interface B2{}
protected interface B3{}
public interface B4{}
//static interface B5{} //redundant for inner interfaces
//abstract interface B6{} //redundant for inner interfaces
}
- 如何实例化成员内部类的对象
public class InnerClassTest {
public static void main(String[] args) {
//创建Dog实例(静态的成员内部类)
Person.Dog dog = new Person.Dog();
dog.show();
//创建Bird实例(非静态的成员内部类)
// Person.Bird bird = new Person.Bird();//错误的
Person p = new Person();
Person.Bird bird = p.new Bird();
bird.sing();
}
}
class Person {
String name;
int age;
public void eat() {
System.out.println("人,吃饭");
}
static class Dog{
String name;
int age;
public void show() {
System.out.println("卡拉是条狗");
}
}
class Bird {
String name;
public void sing() {
System.out.println("我是一只小小鸟");
}
public Bird() {}
}
}
- 如何在成员内部类中区分调用外部内的结构
public class InnerClassTest {
public static void main(String[] args) {
Person.Bird bird = new Person().new Bird();
bird.sing();
bird.display("哈哈,哈哈哈哈");
}
}
class Person {
String name = "Tom";
int age;
public void eat() {
System.out.println("人,吃饭");
}
static class Dog{
String name;
int age;
public void show() {
System.out.println("卡拉是条狗");
}
}
class Bird {
String name = "杜鹃";
public void eat() {
System.out.println("鸟,吃虫");
}
public void sing() {
System.out.println("我是一只小小鸟");
//与外部内未重名的属性、方法调用
Person.this.age = 2;
eat();//this.eat();
}
public void display(String name) {
//调用与外部内重名的属性、方法
System.out.println(name);//形参
System.out.println(this.name);//内部类的属性
System.out.println(Person.this.name);//外部类的属性
eat();//默认省略this.
this.eat();
Person.this.eat();
}
public Bird() {}
}
}
- 在局部内部类的方法中,如果调用外部类中所声明的方法中的局部变量的话,要求此局部变量必须声明为final的。
public class InnerClassTest {
public void method() {
//局部变量
int num = 10;//省略了final关键字。JDK8及之后的版本可以省略,JDK7及之前的版本必须显式的将局部变量声明为final
class AA{
public void show() {
//num = 20;//报错,final修饰的变量不能被重新赋值
System.out.println(num);
}
}
}
}
- 开发中局部内部类的使用
public class InnerClassTest {
public static void main(String[] args) {
}
//开发中很少见
public void method() {
//局部内部类
class AA {}
}
//返回一个实现了Comparable接口的类的对象
public Comparable getComparable() {
//创建一个实现了Comparable接口的类:局部内部类
/*方式一:
class MyComparable implements Comparable {
@Override
public int compareTo(Object o) {
return 0;
}
}
return new MyComparable();
*/
/*方式二:*/
return new Comparable() {
@Override
public int compareTo(Object o) {
return 0;
}
};
}
}