面向对象高级
四种内部类
1.局部内部类
// 局部内部类的使用:
//1.局部内部类是定义在外部类的局部位置,比如方法,有类名
//2.局部内部类可以直接访问外部类的所有成员,包括私有的
//3.外部类访问内部类, 创建对象 在访问 (在作用域中创建)
//4.不能添加访问修饰符,可以用final 修饰 防止其他类继承
//5.作用域 (方法或代码块)
//** 局部内部类定义在方法/代码块中
//** 作用域在方法体或代码块中
//** 本质还是类
//6.外部其他类 不能访问 内部其他类 (例如main方法中)
//7.如果外部其他类和内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用外部类名+this.成员
//实例讲解:
out01 out01 = new out01();
out01.f1();
System.out.println(out01); // out01的地址
}
}
class out01{
private int n = 1;
public void f(){
System.out.println("外部类的方法");
}
public void f1(){ // 方法中定义局部内部类
class inner01{ //final 防止其他内部类的继承
public void f2(){
int n = 5;
System.out.println("n = " + n);
System.out.println("n = " + out01.this.n);
System.out.println("n = " + out01.this);//out01的地址
f();
}
}
inner01 inner01 = new inner01(); // 需要创建对象才能使外部类调用内部类的方法
inner01.f2();
// class inner02 extends inner01 { }
}
{
class inner03{ 在代码块中定义内部类
}
2.匿名内部类(重点)
//匿名内部类的引入: 例如
// 匿名内部类
// 基于接口的匿名内部类
//1.需求:想使用IA接口,并创建对象
//2.传统方式:写一个类,实现该接口,并创建对象
//3.需求: 只使用一次tiger 后面不使用
//4.可以使用匿名内部类简化开发
//5.tiger的编译类型 IA 运行类型 匿名内部类 (只想使用一次,但多个对象的时候,不需要创建多个类来实现接口)
//6.匿名内部类用一次就不能使用了,但是创建的对象还是能使用
out04 out04 = new out04();
out04.method();
}
}
class out04{
private int n = 100;
public void method(){
/*
底层代码 class outer04$1 implements IA{
@Override
public void cry() { //匿名内部类
System.out.println("老虎叫唤");
}
*/
IA ia = new IA() { // 重写方法
@Override
public void cry() { //匿名内部类
System.out.println("老虎叫唤");
}
};
ia.cry();// 创建对象 让外部类调用内部类
System.out.println(ia.getClass());
}
interface IA{
public void cry();
}
//class tiger implements IA{ // 传统方法
//
// @Override
// public void cry() {
// System.out.println("老虎叫唤");
// }
//}
//基于类的匿名继承类 Father
/*
底层代码 class outer04$1 extents Father{
@Override
public void cry() { //匿名内部类
System.out.println("老虎叫唤");
}
}
*/
//使用细节:
//1.匿名内部类即使类的定义同时本身也是个对象,从语法上看,既有定义类的特征,也有创建对象的特征
//2.可以直接访问外部类的所有成员
//3.不能添加访问修饰符
//4.作用域 方法 代码块
//5.匿名内部类访问外部类的下成员 直接访问
//7.外部其他类(例如main中) 不能访问 匿名内部类 (—就是一个局部变量—)
//8.如果外部类和匿名内部类的成员重名时,匿名内部类访问时遵循就近原则 如果想要访问外部类的成员使用外部类名.this.成员
//9.使用场景: 当只需要调用一次时 不需要在写一个类 起方法 只需要写个匿名内部类 既节约了内存 有减轻了代码量
访问方式 两个方式
public class AnonymousInnerClass02 {
public static void main(String [] args){
out05 out05 = new out05();
out05.f1();
}
}
class out05{
private int n1 = 99;
public void f1(){
// 第一种写法
Person person = new Person(){ // 匿名内部类
// public void hi(){
// System.out.println("你好"); //如果没有重写调用哈哈 还是按继承关系运行
// }
};
person.hi(); //运行类型是out05$01
// 第二种写方法
new Person(){
public void ok(){
System.out.println("好的");
}
}.ok(); // 不创建对象 最后.方法;
}
}
class Person{
public void hi(){
System.out.println("哈哈");
}
public void ok(){
System.out.println("okok");
}
}
//小试牛刀
public class AnonymousInnerClass04 {
public static void main(String [] args){
Cellphone cellphone = new Cellphone();
cellphone.alarmClock(new Bell() { // 匿名内部类
@Override
public void ring() {
}
});
x1(new Bell() {
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
x1(new Bell() {
@Override
public void ring() {
System.out.println("小伙伴们上课了");
}
});
}
public static void x1(Bell bell){
bell.ring();
}
}
interface Bell{
public void ring();
}
class Cellphone{
public void alarmClock(Bell bell){ // 写入接口
bell.ring();
}
}
3.成员内部类
// 成员内部类: 定义在外部类的成员位置,并且没有static的修饰
//1.可以直接访问外部类的所有成员
//2.可以添加访问修饰符 因为本身就是成员
//3.作用域: 和其他的外部类的成员方法一样,在外部类的方法中创建对象 在调用对象
//4.成员内部类 访问 外部类 直接访问
//5.外部类访问内部类 创建对象在访问***
//6.外部其他类访问成员内部类
//7.重名用this 用法和之前一样
//实例讲解
out out = new out();
out.t1();
//5.外部类访问内部类 创建对象在访问 一 先写类名 在new 内部类
MemberInnerClass.out.inner inner = out.new inner();
inner.m();
// 二 在外部类写一个方法 返回inner的对象
MemberInnerClass.out.inner instance = out.getInstance();
instance.m();
}
}
class out{
private int n1 = 100;
class inner {
int n1 = 520;
public void m(){
System.out.println("n1 = " + n1 + " 外部类的" + out.this.n1);
}
}
public void t1(){ // 创建公共的方法
inner inner = new inner();
inner.m();
}
public inner getInstance(){
return new inner();
}
}
4.静态内部类
//静态内部类 定义在外部类的成员位置 用static修饰
//1.可以直接访问外部类的静态成员 但是不能访问非静态成员
//2.可以添加访问修饰符,本身就是成员
//3.作用域 同类的其他成员,为整个类体
//4.静态内部类访问外部类的静态成员 直接访问
//5.外部类访问静态内部类 创建对象在访问
//6.重名 和this的机制一样但是不使用this 外部类名.属性
//实例讲解
out01.inner01 inner01 = new out01.inner01(); // 一 可通过类名直接访问
inner01.m1();
out01 out01 = new out01();
out01.t2();
// 编写一个方法 返回对象
StaticClass.out01.inner01 inner011 = out01.get();
inner011.m1();
}
}
class out01{
public static int n1 = 1314;
static class inner01{
int n1 = 666;
public void m1(){
System.out.println(n1 + " " + out01.n1);
}
}
public static void t2(){
inner01 inner01 = new inner01();
inner01.m1();
}
public static inner01 get(){
return new inner01();
}
}