目录
类的五大成员:属性、方法、构造器、代码块、内部类
内部类的分类
定义在外部类局部位置上(比如说方法内):定义在外部类的成员位置上:
- 局部内部类(有类名)
- 匿名内部类(没有类名)
- 成员内部类(没用static修饰)
- 静态内部类(使用static修饰)
一、局部内部类
说明:局部内部类是定义在外部类的局部位置,比如方法种,并且有类名- 可以直接访问外部类的所有成员,包含私有的
- 不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以使用final
- 作用域:仅仅在定义它的方法或代码块中。
- 局部内部类---访问----》外部类的成员 【访问方式:直接访问】
- 外部类---访问---》局部内部类的成员
- 访问方式:创建对象,再访问(注意:必须再作用域内)
package com.hspedu.innerclass;
/**
* 演示局部内部类的使用
*/
public class LocalInnerClass {
public static void main(String[] args) {
//演示一遍
Outer02 outer02 = new Outer02();
outer02.m1();
}
}
class Outer02 {//外部类
private int n1 = 100;
private void m2() {
System.out.println("Outer02 m2()");
}//私有方法
public void m1() {//方法
//1.局部内部类是定义在外部类的局部位置,通常在方法
//3.不能添加访问修饰符,但是可以使用final修饰
//4.作用域:仅仅在定义它的方法或代码块中
class Inner02 {//局部内部类(本质仍然是一个类)
//2.可以直接访问外部类的所有成员,包含私有的
public void f1() {
//5.局部内部类可以直接访问外部类的成员,比如下面 外部类n1 和 m2()
System.out.println("n1=" + n1);
m2();
}
}
//6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
Inner02 inner02 = new Inner02();
inner02.f1();
}
}
输出结果
- 外部其他类---》不能访问---》局部内部类(因为 局部内部类地位是一个局部变量)
- 如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
Outer02.this 本质就是外部类的对象,即哪个对象调用了m1,Outer02.this就是哪个对象
输出结果:
二、匿名内部类
本质是类 内部类 该类没有名字 同时还是一个对象
说明:匿名内部类是定义在外部类的局部位置,比如方法中,并且没有类名
匿名内部类的基本语法
new类或接口(参数列表){
类体
};
基于接口的匿名内部类
未使用匿名内部类简化开发之前
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.可以使用匿名内部类来简化开发
IA tiger = new Tiger();
tiger.cry();
}
}
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) {//构造器
}
public void test() {//方法
}
}
使用匿名内部类简化开发之后
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的运行类型 ? 就是匿名内部类 XXXX => Outer04$1
/*
我们看底层 会分配 类名 Outer04$1
class XXXX 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("老虎叫----");
}
};
tiger.cry();
System.out.println("tiger的运行类型:" + tiger.getClass());
// IA tiger = new Tiger();
// tiger.cry();
}
}
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) {//构造器
}
public void test() {//方法
}
}
要注意这段代码并不是直接创建接口的实例,而是创建了一个实现类该接口的类的实例,
这个类的类名由jdk分配
匿名内部类的代码:
IA tiger = new IA(){
@Override
public void cry() {
System.out.println("老虎叫----");
}
};
实际上等价于下面的代码
// 显式定义一个类实现接口
class Outer04$1 implements IA {
@Override
public void cry() {
System.out.println("老虎叫----");
}
}
// 在主方法中创建 MyPrinter 的对象
IA tiger = new Outer04$1();
基于类的匿名内部类
class Father {//类
public Father(String name) {//构造器
}
public void test() {//方法
}
}
//演示基于类的匿名内部类
//分析
//1.father编译类型 Father
//2.father运行类型 Outer04$2
//3.底层会创建匿名内部类
/*
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
}
*/
//4.同时也直接返回了 匿名内部类 Outer04$2
//注意("jack") 参数列表会传递给构造器
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
System.out.println("father对象的运行类型=" + father.getClass());//Outer04$2
father.test();
Father father = new Father("jack"){
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
};
等价于
class Outer04$2 extends Father{
@Override
public void test() {
System.out.println("匿名内部类重写了test方法");
}
}
Father father = new Outer04$2("jack");
基于类的匿名内部类的第二种方式,这里我调用的是Person类
//直接调用,匿名内部类本身也是返回对象
//class 匿名内部类 extends Person {}
new Person(){
@Override
public void hi() {
System.out.println("匿名内部类重写了 hi方法,zzzzzz");
}
}.hi();
package com.hspedu.innerclass;
public class AnonymousInnerClassDetail {
public static void main(String[] args) {
Outer05 outer05 = new Outer05();
outer05.f1();
//外部其他类---不能访问----》匿名内部类
System.out.println("main hashcode=" + outer05);
}
}
class Outer05 {
private int n1 = 99;
public void f1() {
//创建一个基于类的匿名内部类
//不能添加访问修饰符,因为它的地位就是一个局部变量
//作用域:仅仅在定义它的方法或代码块中
Person p = new Person(){
private int n1 = 88;
@Override
public void hi() {
//可以直接访问外部类的所有成员,包含私有的
//如果外部类和匿名内部类的成员重名时,匿名内部类访问的话
//默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员) 去访问
System.out.println("匿名内部类重写了 hi方法 n1=" + n1 + " 外部内的n1=" + Outer05.this.n1);
//Outer05.this 就是调用 f1的 对象
System.out.println("Outer05.this hashcode=" + Outer05.this);
}
};
p.hi();//动态绑定,运行类型是Outer05$1
// //也可以直接调用,匿名内部类本身也是返回对象
// //class 匿名内部类 extends Person {}
// new Person(){
// @Override
// public void hi() {
// System.out.println("匿名内部类重写了 hi方法,zzzzzz");
// }
//
// @Override
// public void ok(String str) {
// super.ok(str);
// }
// }.ok("jack");
}
}
class Person {//类
public void hi(){
System.out.println("Person hi()");
}
public void ok(String str){
System.out.println("Person ok()" + str);
}
}
//抽象类/接口。。。
三、匿名内部类的实践
示例1
匿名内部类方式
public class InnerClassExercise01 {
public static void main(String[] args) {
//当作实参直接传递,简洁高效
f1(new IL() {
@Override
public void show() {
System.out.println("这是一幅画。。。");
}
});
}
//静态方法,形参是接口类型
public static void f1(IL il){
il.show();
}
}
//接口
interface IL {
void show();
}
传统方式
public class InnerClassExercise01 {
public static void main(String[] args) {
//传统写法
f1(new Picture());
}
//静态方法,形参是接口类型
public static void f1(IL il){
il.show();
}
}
//接口
interface IL {
void show();
}
//类->实现IL =》编程领域(硬编码)
class Picture implements IL {
@Override
public void show() {
System.out.println("这是一幅名画。。。。");
}
}
示例2
package com.hspedu.innerclass;
public class InnerClassExercise02 {
public static void main(String[] args) {
CellPhone cellPhone = new CellPhone();
cellPhone.alarmClock(new Bell() {//匿名内部类
@Override
public void ring() {
System.out.println("懒猪起床了");
}
});
}
}
interface Bell{//接口
void ring();//方法
}
class CellPhone{//类
public void alarmClock(Bell bell){//形参是Bell接口类型
bell.ring();//动态绑定
}
}
标签:Java,内部,void,public,匿名,println,class
From: https://blog.csdn.net/jlihan/article/details/144521559