类的五大成员:属性、方法、构造器、代码块、内部类
内部类:一个类的内部又完整地嵌套了另一个类结构,嵌套的类称为内部类、被嵌套的类称为外部类。
内部类最大的特点:可以直接访问私有属性,并且可以体现类与类之间的包含关系
基本语法:
class Outer{ //外部类
class Inner { //内部类
}
}
class Other {//其他类
}
内部类的分类:
1、定义在外部类的局部位置上(比如方法内):
(1)局部内部类(有类名)
(2)匿名内部类(没有类名,重点)
2、定义在外部类的成员位置上:
(1)成员内部类(没有static修饰)
(2)静态内部类(使用static修饰)
一、局部内部类
定义:定义在外部类的局部位置,比如方法中,而且有类名
细节:
1、可以直接访问外部类的所有成员,包含私有的
2、不能添加访问修饰符,因为局部内部类的地位是一个局部变量,局部变量是不能使用修饰符的,但是可以使用final修饰,因为局部变量可以使用final修饰
3、作用域:仅仅在定义它的方法或代码块中。
4、局部内部类可以直接访问外部类的成员。
5、外部类----访问-----局部内部类的成员的方式:创建对象再访问,外部类在方法中,可以创建内部类对象,然后调用方法即可
局部内部类定义在方法中 /代码块中,作用域在方法体/代码块中,本质仍然是一个类
6、外部其他类--不能访问局部内部类(因为局部内部类地位是一个局部变量)
7、如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,使用外部类名.this.成员名去访问
Outer.this本质是外部类的对象,即哪个对象调用了方法,Outer.this就是哪个对象
二、匿名内部类
前提:(1)本质是类(2)内部类(3)匿名,该类没有显式名字,系统自定隐藏(4)同时是一个对象
说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
1、匿名内部类的基本语法:
new 类或接口(参数列表) {
类体
};
2、使用匿名内部类的原因:简化开发;
package com.hspedu.innerclass;
/**
* 演示匿名内部类的使用
*/
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer04 outer04 = new Outer04();
outer04.method();
}
}
class Outer04 { //外部类
private int n1 = 10;//属性
public void method() {//方法
//基于接口的匿名内部类
//老韩解读
//1.需求: 想使用IA接口,并创建对象
//2.传统方式,是写一个类,实现该接口,并创建对象
//3.老韩需求是 Tiger/Dog 类只是使用一次,后面再不使用
//4. 可以使用匿名内部类来简化开发
//5. tiger的编译类型 ? IA
//6. tiger的运行类型 ? 就是匿名内部类 Outer04$1
/*
我们看底层 会分配 类名 Outer04$1
class Outer04$1 implements IA {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
}
*/
//7. jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了 Outer04$1实例,并且把地址
// 返回给 tiger
//8. 匿名内部类使用一次,就不能再使用,但是整个对象实例可以继续用
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("老虎叫唤...");
}
};
System.out.println("tiger的运行类型=" + tiger.getClass());
tiger.cry();
tiger.cry();
tiger.cry();
// IA tiger = new Tiger();
// tiger.cry();
//演示基于类的匿名内部类
//分析
//1. father编译类型 Father
//2. father运行类型 Outer04$2
//3. 底层会创建匿名内部类
/*
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
}
*/
//4. 同时也直接返回了 匿名内部类 Outer04$2的对象
//5. 注意("jack") 参数列表会传递给 构造器
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father对象的运行类型=" + father.getClass());//Outer04$2
father.test();
//基于抽象类的匿名内部类
Animal animal = new Animal(){
@Override
void eat() {
System.out.println("小狗吃骨头...");
}
};
animal.eat();
}
}
interface IA {//接口
public void cry();
}
//class Tiger implements IA {
//
// @Override
// public void cry() {
// System.out.println("老虎叫唤...");
// }
//}
//class Dog implements IA{
// @Override
// public void cry() {
// System.out.println("小狗汪汪...");
// }
//}
class Father {//类
public Father(String name) {//构造器
System.out.println("接收到name=" + name);
}
public void test() {//方法
}
}
abstract class Animal { //抽象类
abstract void eat();
}
3、匿名内部类细节:
4、匿名内部类练习:
将匿名内部类当作实参直接传递,简洁高效
public class IE01 {
public static void main(String[] args) {
f1(new IL() {
@Override
public void show() {
System.out.println("这是f1-anony");
};
});
}
//静态方法,形参是接口类型
public static void f1(IL il) {
il.show();
}
}
interface IL {
void show();
}
三、成员内部类
四、静态内部类
public class StaticInnerClass01 {
public static void main(String[] args) {
Outer10 outer10 = new Outer10();
outer10.m1();
//外部其他类 使用静态内部类
//方式1
//因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
Outer10.Inner10 inner10 = new Outer10.Inner10();
inner10.say();
//方式2
//编写一个方法,可以返回静态内部类的对象实例.
Outer10.Inner10 inner101 = outer10.getInner10();
System.out.println("============");
inner101.say();
Outer10.Inner10 inner10_ = Outer10.getInner10_();
System.out.println("************");
inner10_.say();
}
}
class Outer10 { //外部类
private int n1 = 10;
private static String name = "张三";
private static void cry() {}
//Inner10就是静态内部类
//1. 放在外部类的成员位置
//2. 使用static 修饰
//3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
//4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
//5. 作用域 :同其他的成员,为整个类体
static class Inner10 {
private static String name = "韩顺平教育";
public void say() {
//如果外部类和静态内部类的成员重名时,静态内部类访问的时,
//默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)
System.out.println(name + " 外部类name= " + Outer10.name);
cry();
}
}
public void m1() { //外部类---访问------>静态内部类 访问方式:创建对象,再访问
Inner10 inner10 = new Inner10();
inner10.say();
}
public Inner10 getInner10() {
return new Inner10();
}
public static Inner10 getInner10_() {
return new Inner10();
}
}