深入了解Java内部类的用法
1.内部类分类和概念
java类的五大成员:属性,方法,构造器(构造方法),代码块,内部类
内部类的分类:
定义在外部类局部的位置(比如方法内):
- 局部内部类(有类名)
- 匿名内部类(无类名)
定义在外部类成员位置上:
- 成员内部类(没有static修饰)
- 静态内部类(有static修饰)
概念:在一个类的内部再定义一个完整的类,也会生成一个class文件
代码示例:
public class InnerClass {
private int n = 521;
public InnerClass(int n) {
this.n = n;
}
class Inner { // 内部类
}
}
谨记:内部类很重要,java底层源码内部类使用场景很多!
2.局部内部类
class Outer001 { // 外部类
private int n = 521;
private void kaka() {
System.out.println("我是外部类的方法!");
}
public void show() {
// 局部内部类定义在外部类的局部位置,通常在方法中
class Inner001 {
// 局部内部类
public void f() {
// 可以直接访问外部类的所有成员,包含私有的
System.out.println(n);
}
}
}
}
不能添加访问修饰符,但是可以添加final
局部内部类的作用域只在定义它的方法或者代码块中
外部类使用内部类的方法,直接new即可:
public void show() {
// 局部内部类定义在外部类的局部位置,通常在方法中
final class Inner001 {
// 局部内部类
public void f() {
// 可以直接访问外部类的所有成员,包含私有的
System.out.println(n);
kaka();
}
}
// 外部类使用内部类的方法
Inner001 inner001 = new Inner001();
inner001.f();
}
外部其他类不能访问局部内部类!
外部类和局部内部类的成员重名时,默认遵循就近原则,如果想要访问外部类的成员,使用外部类名.this.成员进行访问
3.匿名内部类(重要)
匿名内部类其实有名字,它的名字是底层的jdk给分配的~系统分配该类名的时候会在外部类的基础上加上$1,存在多个内部类的,$后面的值进行递增
基于接口的匿名内部类
public class AnonymousInnerClass {
public static void main(String[] args) {
Outer002 outer002 = new Outer002();
outer002.method();
}
}
class Outer002 {
private int n = 521;
public void method() {
// 基于接口的匿名内部类
// tiger的编译类型是IA,运行类型就是匿名内部类!
// 系统分配该类名的时候会在外部类的基础上加上$1,此处是Outer002$1
// JDK底层在创建了匿名内部类之后,立即创建了一个实例,并且把地址返回给tiger
IA tiger = new IA() {
@Override
public void cry() {
System.out.println("我是一只小老虎?");
}
};
tiger.cry();
System.out.println(tiger.getClass());
}
}
interface IA {
public void cry();
}
输出:
我是一只小老虎?
class seNIOrobject.innerclass.Outer002$1
注意:匿名内部类使用一次就不能再使用了!
基于类的匿名内部类
基于类的匿名内部类和基于接口的差不太多
Father类:
class Father {
private String name;
public Father(String name) {
this.name = name;
}
public void test() {
}
}
匿名内部类:
// 基于类的匿名内部类,加入大括号就摇身一变变成内部类了
Father jack = new Father("jack"){
@Override
public void test() {
super.test();
System.out.println("♪(^∇^*)");
}
};
System.out.println(jack.getClass());
输出:
class seniorobject.innerclass.Outer002$2
一些细节
匿名内部类是类,同时,它也可以理解为是一个对象
匿名内部类可以访问外部类的所有成员,包括私有的
不能添加访问修饰符
定义域在定义它的方法或者代码块中,转瞬即逝!
外部其他类不能访问匿名内部类
外部类和匿名内部类成员重名时,参照局部内部类的方式即可
匿名内部类的最佳实践
当作实参直接传递,简洁高效
public class AnonymousInnerClassPractice {
public static void main(String[] args) {
f(new IL() {
@Override
public void show() {
System.out.println("你好啊");
}
});
}
public static void f(IL il) {
il.show();
}
}
interface IL {
void show();
}
4.成员内部类
定义在外部类的成员位置上:
实例:
public class MemberInnerClass {
public static void main(String[] args) {
Outer003 outer003 = new Outer003();
outer003.t();
}
}
class Outer003 {
private int n = 521;
public String name = "dahe";
class Inner003 { // 成员内部类
public void say() {
System.out.println(n + name);
}
}
public void t() {
// 使用成员内部类
Inner003 inner003 = new Inner003();
inner003.say();
}
}
输出:
521dahe
可以访问外部类的所有成员,包括私有的
可以添加任意的访问修饰符
作用域为整个类体中
外部类想要使用成员内部类,创建对象调用即可!
外部其他类想要访问成员内部类,存在两种方式:
// 直接创建对象
Outer003.Inner003 inner003 = outer003.new Inner003();
// 注意:这里的outer003是外部类的对象实例
// 成员内部类的外部类创建一个返回内部类对象的公有方法
public Inner003 getInner003Instance() {
return new Inner003();
}
// 外部其他类进行调用该共有方法
Outer003.Inner003 inner0031 = outer003.getInner003Instance();
inner0031.say();
外部类和成员内部类的成员重名时,参考局部内部类和匿名内部类即可
5.静态内部类
可以直接访问外部类的静态成员
可以添加任意的访问修饰符
作用域为整个类体
外部类想要访问静态内部类依然是创建对象访问
外部其他类想要访问静态内部类:
// 通过类名直接访问
Outer004.Inner004 inner004 = new Outer004.Inner004();
inner004.say();
// 静态内部类的外部类创建一个返回内部类对象的公有方法
// 返回静态内部类的对象实例
public Inner004 getInner004() {
return new Inner004();
}
Outer004.Inner004 inner0041 = outer004.getInner004();
inner0041.say();
// 返回静态内部类的对象实例,但是是静态方法
public static Inner004 getInner004_() {
return new Inner004();
}
// 静态内部类的外部类创建一个返回内部类对象的公有静态方法
Outer004.Inner004 inner0042 = Outer004.getInner004_();
inner0042.say();
整体代码示例:
public class StaticInnerClass {
public static void main(String[] args) {
Outer004 outer004 = new Outer004();
// 通过类名直接访问
Outer004.Inner004 inner004 = new Outer004.Inner004();
inner004.say();
// 静态内部类的外部类创建一个返回内部类对象的公有方法
Outer004.Inner004 inner0041 = outer004.getInner004();
inner0041.say();
// 静态内部类的外部类创建一个返回内部类对象的公有静态方法
Outer004.Inner004 inner0042 = Outer004.getInner004_();
inner0042.say();
}
}
class Outer004 {
private int n = 521;
private static String name = "dahe";
public static class Inner004 {
public void say() {
// 可以直接访问外部类的静态成员
System.out.println(name);
}
}
// 返回静态内部类的对象实例
public Inner004 getInner004() {
return new Inner004();
}
// 返回静态内部类的对象实例,但是是静态方法
public static Inner004 getInner004_() {
return new Inner004();
}
}
外部类和成员内部类的成员重名时,遵循就近原则,如果想要访问外部类的成员,使用外部类名.成员即可
以上就是深入了解Java内部类的用法的详细内容,更多关于Java内部类的资料请关注其它相关文章!
相关文章