一个类的内部又嵌套了另一个类 --> 内部类
1.定义在局部位置(方法/代码块)
1)局部内部类(有类名)
2)匿名内部类(无类名)
2.定义在成员位置
1)成员内部类
2)静态内部类
1.什么是局部内部类?
——将类定义在另一个类的内部方法或代码块中
2.局部内部类的格式
class 类名 {
//1)定义在方法中
权限修饰符 返回类型 方法名(形参列表...) {
class 类名 {
}
}
//2)定义在代码块中
{
class 类名 {
}
}
}
public class Test {
public static void main(String[] args) {
}
}
class Person {
public void say() {
//1)定义在方法中
class Teacher {}
}
//2)定义在代码块中
{
class Student {}
}
}
3.一个小case快速了解局部内部类
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
private int age = 10;
public void hello() {
//1)定义在方法中
class Teacher {
private int num = 20;
public void hi() {
System.out.println("hi~");
System.out.println(num);
}
}
//访问局部内部类的属性
Teacher teacher = new Teacher();
teacher.hi();
}
//2)定义在代码块中
{
class Student {
public void say() {
System.out.println("say~");
System.out.println(age);
}
}
//访问局部内部类的属性
Student student = new Student();
student.say();
}
}
4.局部内部类的细节讨论及实现
1)局部内部类可以直接访问外部类的所有成员,包括私有的属性
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
int num = 130;
public double price = 13001.13;
public void hello() {
class Teacher {
public void hi() {
//局部内部类可以直接访问外部类的所有成员,包括私有的属性
System.out.println(age);
System.out.println(num);
System.out.println(price);
go();
}
}
//访问局部内部类的属性
Teacher teacher = new Teacher();
teacher.hi();
}
//外部类的方法
public void go() {
System.out.println("bro,go go go~");
}
}
2)局部内部类不能添加访问修饰符,因为它本身的地位就是一个局部变量(局部变量不能使用访问修饰符,但是能使用final关键字修饰)
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
//局部内部类不能任何访问修饰符,因为局部内部类本质上是局部变量
//public class Stu{}
//局部内部类可以使用final修饰
final class Teacher {
public void hi() {
System.out.println(age);
go();
}
}
//访问局部内部类的属性
Teacher teacher = new Teacher();
teacher.hi();
}
public void go() {
System.out.println("bro,go go go~");
}
}
3)局部内部类的作用域:在定义它的方法中或代码块中
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
//局部内部类的作用域:在定义它的方法中或代码块中
public void hello() {
class Teacher {
public void hi() {
System.out.println(age);
go();
}
}
//访问局部内部类的属性
Teacher teacher = new Teacher();
teacher.hi();
}
//除了所在的作用域(hello方法内)后,无法使用
public void go() {
//Teacher teacher = new Teacher();//错误
}
}
4)局部内部类本质是还是类,遵守类的一切规定
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
//局部内部类本质是还是类,遵守类的一切规定
class Teacher {
//属性
private int num;
public static int AGE = 100;
//构造器
public Teacher() {}
//方法
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
}
}
5)外部类访问局部内部类的成员:创建对象,再访问(需在作用域内)
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
class Teacher {
public void get() {
System.out.println(age);
}
}
//外部类访问局部内部类的成员:创建对象,再访问(需在作用域内)
Teacher teacher = new Teacher();
teacher.get();
}
}
6)外部其他类不能访问局部内部类,因为局部内部类的地位就是局部变量
public class Test {
public static void main(String[] args) {
//外部其他类不访问局部内部类,因为局部内部类的地位就是局部变量
//Test是外部其他类
//Teacher teacher = new Teacher();//不能访问
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
class Teacher {
public void get() {
System.out.println(age);
}
}
}
}
7)外部类的成员与局部内部类的成员重名的时候,访问的时候遵循就近原则,若要访问同名的外部类的成员,使用 外部类名.this.类名 访问
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
class Teacher {
public int age = 20;
//外部类的成员与内部类的成员重名的时候,访问的时候遵循就近原则,
//若要访问同名的外部类的成员,使用 外部类名.this.类名 访问
public void get() {
System.out.println(age);//20
//理解:谁调用这个对象就是指谁
System.out.println(Person.this.age);//10
}
}
//访问局部内部类
Teacher teacher = new Teacher();
teacher.get();
}
}
1.什么是匿名内部类?
——匿名内部类是没有类名的类,它只能存在于另一个类的方法中或代码块中
2.匿名内部类的格式
new 类名/接口(形参列表...) {
//类体
};
//在底层原理中,匿名内部类实现接口或继承类(重点)
//当要把匿名内部类的地址返回给一个实例时,实例获得地址
3.一个小case快速了解匿名内部类
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
person.hi();
}
}
//接口
interface Usb {
void set();
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
//基于类的匿名内部类
//使用方式1
//匿名内部类使用一次就销毁
new Teacher() {
public void hi() {
System.out.println("hi~ I love you~");
}
}.hi();
//使用方式2
//把匿名内部类的地址返回给teacher实例
Teacher teacher = new Teacher() {
//这个地方是继承父类,如果父类中没有对应方法则报错
public void say() {
System.out.println("hello~");
}
};
teacher.say();
}
public void hi() {
//基于接口的匿名内部类
new Usb() {
@Override
public void set() {
System.out.println("connection~");
}
}.set();
}
}
class Teacher {
public void say() {
}
}
4.匿名内部类真的没有类名吗?
——匿名内部类是有类名的,这个类名是有系统分配的,一般命名为包名.外部类$数字
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
//编译类型: Teacher
//运行类型?
Teacher teacher = new Teacher() {
//这个地方是继承父类,如果父类中没有对应方法则报错
public void say() {
System.out.println("hello~");
}
};
//查看匿名内部类的运行类型
System.out.println(teacher.getClass());//class inner.Person$1
}
}
class Teacher {
public void say() {
}
}
5.匿名内部类的细节讨论及实现
1)匿名内部类既是一个类的定义,同时也是一个对象(含有定义类和创建对象的特征)
2)匿名内部类可以直接访问外部类的所有成员,包括私有的
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public double rate = 0.03;
public void hello() {
Teacher teacher = new Teacher() {
public void say() {
//匿名内部类可以直接访问外部类的所有成员,包括私有的
System.out.println(age);//10
System.out.println(rate);//0.03
}
};
teacher.say();
}
}
class Teacher {
public void say() {
}
}
3)不能添加访问修饰符,它本身的地位就是局部变量
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
//不能添加访问修饰符,它本身的地位就是局部变量
//public new Teacher() {}//错误
//能使用final
final Teacher teacher = new Teacher() {
public void say() {
System.out.println("hi~ bro~");
}
};
teacher.say();
}
}
class Teacher {
public void say() {
}
}
4)作用域:定义的方法或代码块中
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
Teacher teacher = new Teacher() {
public void say() {
System.out.println("hi~ bro~");
}
};
teacher.say();
}
//作用域:定义匿名内部类的方法或代码块中
//teacher.say();//错误,不在作用域内
public void set() {
//teacher.say();//错误,不在作用域内
}
}
class Teacher {
public void say() {
}
}
5)外部其他类不能访问匿名内部类(匿名内部类的地位本质是局部变量)
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
//外部其他类不能访问匿名内部类(匿名内部类的地位本质是局部变量)
//Test是外部其他类
//teacher.say();//错误,不能访问
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
Teacher teacher = new Teacher() {
public void say() {
System.out.println("hi~ bro~");
}
};
teacher.say();
}
}
class Teacher {
public void say() {
}
}
6)外部类的成员与匿名内部类的成员重名的时候,访问的时候遵循就近原则,若要访问同名的外部类的成员,使用 外部类名.this.类名 访问
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.hello();
}
}
class Person {
//外部类的属性
private int age = 10;
public void hello() {
Teacher teacher = new Teacher() {
private int age = 20;
public void say() {
System.out.println(age);//20
//访问同名的外部类的成员,使用 外部类名.this.类名 访问
System.out.println(Person.this.age);//10
}
};
teacher.say();
}
}
class Teacher {
public void say() {
}
}
6.匿名内部的实践 —— 作为实参传递
1)基于接口作为实参
public class Test {
public static void main(String[] args) {
//匿名内部类作为实参传递
fulfill(new Usb() {
public void set() {
System.out.println("创建成功~");
}
public void connect() {
System.out.println("连接成功~");
}
});
}
//形参使用接口接收
public static void fulfill(Usb usb) {
usb.set();
usb.connect();
}
}
interface Usb {
void set();
void connect();
}
2)基于类作为实参
public class Test {
public static void main(String[] args) {
//匿名内部类作为实参传递
fulfill(new Teacher() {
public void hello() {
System.out.println("hello~ 小朋友~");
}
});
}
//形参使用接口接收
public static void fulfill(Teacher teacher) {
teacher.hello();
}
}
class Teacher {
public void hello() {}
}
1.什么是成员内部类?
——成员内部类位于另一个类的成员位置上,本质就是外部类的一个成员
2.成员内部类的格式
class 类名 {
//属性和方法
class 类名 {
//属性和方法
}
}
3.一个小case快速了解成员内部类
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.age = 19;
//外部其他类访问成员内部类
Person.Teacher teacher = person.new Teacher("jack");
teacher.get();
}
}
//成员内部类的演示
class Person {
//外部属性
public int age;
private char gender = '男';
//外部构造器
public Person() {
}
//成员内部类
class Teacher {
//内部属性
public String name;
public Teacher(String name) {
this.name = name;
}
public void get() {
System.out.println(name);
System.out.println(age);
System.out.println(gender);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
4.成员内部类的细节讨论及实现
1)可以直接访问外部类的所有成员,包括私有的
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.age = 19;
//外部其他类访问成员内部类
Person.Teacher teacher = person.new Teacher();
teacher.get();
}
}
//成员内部类的演示
class Person {
//外部属性
public int age;
private char gender = '男';
//成员内部类
class Teacher {
public void get() {
//成员内部类能直接访问外部类的所有成员,包括私有的
System.out.println(age);
System.out.println(gender);
}
}
}
2)可以添加任意的权限访问修饰符(public、protected、默认、private),因为成员内部类的地位就是外部类的一个成员
public class Test {
public static void main(String[] args) {
}
}
//成员内部类的演示
class Person {
//外部属性
public int age;
private char gender = '男';
//成员内部类
//可以添加任意的权限访问修饰符(public、protected、默认、private)
public class Teacher {}
protected class Stu {}
class Student {}
private class Colleague {}
}
3)作用域和外部类的其他成员相同,为整个类体
public class Test {
public static void main(String[] args) {
Person person = new Person();
//外部可以访问创建成员内部类
Person.Teacher teacher = person.new Teacher();
teacher.get();
}
}
//成员内部类的演示
class Person {
//外部属性
public int age;
private char gender = '男';
//成员内部类
//作用域和外部类的其他成员相同,为整个类体
class Teacher {
public void get() {
System.out.println("外部能创建实例对象~");
}
}
}
4)外部类访问成员内部类:创建对象进行访问
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.assess();
}
}
//成员内部类的演示
class Person {
//外部属性
public int age;
private char gender = '男';
//成员内部类
class Teacher {
public void get() {
System.out.println("外部类访问成员内部类~");
}
}
//外部类访问成员内部类:创建对象进行访问
public void assess() {
Teacher teacher = new Teacher();
teacher.get();
}
}
5)外部其他类访问成员内部类的形式
a.直接创建对象访问
外部类名.成员内部类名 对象名 = 外部类名的实例.new 成员内部类类名(参数);
b.外部类中通过返回一个成员内部类的对象实例来进行访问
class 外部类 {
class 成员内部类 {
}
//提供返回成员内部类的实例对象的方法
public 成员内部类名 方法名() {
//返回实例对象
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
//外部其他类访问成员内部类
//1.直接创建对象访问
Person.Teacher teacher = person.new Teacher();
teacher.get();
//2.外部类提供公共的内部类实例方法
Person.Teacher teacher1 = person.getInstance();
teacher1.get();
}
}
//成员内部类的演示
class Person {
//外部属性
public int age;
private char gender = '男';
//成员内部类
class Teacher {
public void get() {
System.out.println("外部其他类访问成员内部类~");
}
}
//返回成员内部类的实例对象
public Teacher getInstance() {
return new Teacher();
}
}
6)若外部类和成员内部类的成员名相同时,按照就近原则访问,若要访问外部类的属性,则使用外部类名.this.属性名访问
public class Test {
public static void main(String[] args) {
Person person = new Person();
Person.Teacher teacher = person.new Teacher();
teacher.get();
}
}
//成员内部类的演示
class Person {
//外部属性
private char gender = '男';
//成员内部类
class Teacher {
private char gender = '女';
public void get() {
System.out.println(gender);//女
//访问外部类的t同名属性,则使用外部类名.this.属性名访问
System.out.println(Person.this.gender);//男
}
}
}
1.什么是静态内部类?
——在外部类的成员位置上使用static又定义了一个类,这个类叫做静态内部类
2.静态内部类的格式
class 类名 {
//属性和方法
static class 类名 {
//属性和方法
}
}
3.一个小case快速了解静态内部类
public class Test {
public static void main(String[] args) {
}
}
class Person {
//外部属性
public int age;
private char gender = '男';
//静态内部类
static class Teacher {
public void get() {
System.out.println("外部其他类访问成员内部类~");
}
}
}
4.静态内部类的细节讨论及实现
1)可以直接访问外部的所有静态成员(包含私有的),但不能访问非静态成员
public class Test {
public static void main(String[] args) {
Person person = new Person();
//创建Teacher的实例对象
Person.Teacher teacher = new Person.Teacher();
teacher.get();
}
}
class Person {
//外部属性
public static int age = 100;
private char gender = '男';
//静态内部类
//可以直接访问外部的所有静态成员(包含私有的),但不能访问非静态成员
static class Teacher {
public void get() {
//可以直接访问外部的所有静态成员(包含私有的)
System.out.println(age);//100
//不能访问非静态成员
//System.out.println(gender);//错误,gender不是静态成员
}
}
}
2)可以添加任意的访问修饰符(public、protected、默认、private),静态内部类的本质是外部类的成员
public class Test {
public static void main(String[] args) {
}
}
class Person {
//外部属性
public static int age = 100;
private char gender = '男';
//静态内部类
//可以添加任意的访问修饰符(public、protected、默认、private)
public static class Teacher {}
protected static class Stu {}
static class Scientist {}
private static class Colleague {}
}
3)作用域:整个类体均可使用
public class Test {
public static void main(String[] args) {
Person person = new Person();
Person.Teacher teacher = person.getTeacher();
teacher.get();
}
}
class Person {
//外部属性
public static int age = 100;
//静态内部类
static class Teacher {
public void get() {
System.out.println("静态内部类的作用域是整个类体~");
}
}
//作用域:整个类体均可使用
public Teacher getTeacher() {
return new Teacher();
}
}
4)外部类访问静态内部类:创建对象进行访问
public class Test {
public static void main(String[] args) {
Person person = new Person();
person.getResult();
}
}
class Person {
//外部属性
public static int age = 100;
//静态内部类
static class Teacher {
public void get() {
System.out.println("外部类要创建对象才能访问静态内部类~");
}
}
//外部类访问静态内部类:创建对象进行访问
public void getResult() {
Teacher teacher = new Teacher();
teacher.get();
}
}
5)外部其他类访问静态内部类:
a.直接创建静态内部类进行访问
b.让外部类提供public方法得到静态内部类实例,然后访问
public class Test {
public static void main(String[] args) {
//直接创建静态内部类进行访问
Person.Teacher teacher = new Person.Teacher();
teacher.get();
//让外部类提供public方法得到静态内部类实例,然后访问
Person person = new Person();
Person.Teacher teacher1 = person.getInstance();
teacher1.get();
}
}
class Person {
//外部属性
public static int age = 100;
//静态内部类
static class Teacher {
public void get() {
System.out.println("外部其他类访问静态内部类~");
}
}
//外部类访问静态内部类:创建对象进行访问
public Teacher getInstance() {
return new Teacher();
}
}
6)若外部类和静态内部类的成员名相同时,按照就近原则访问,若要访问外部类的属性,则使用外部类名.属性名访问
public class Test {
public static void main(String[] args) {
Person.Teacher teacher = new Person.Teacher();
teacher.get();
}
}
class Person {
//外部属性
public static int age = 200;
//静态内部类
static class Teacher {
public static int age = 100;
public void get() {
System.out.println(age);//100
//若要访问外部类的属性,则使用 外部类名.属性名 访问
System.out.println(Person.age);//200
}
}
}