学习总结:
链接:【Java基础、springboot、springcloud、docker 等,学习目录】
内部类:
一个类定义在另外一个类的内部,那么就称该类为内部类。内部类的class文件名:外部类名$内部类名·class。 内部类分为 成员内部类、局部内部类、匿名内部类。
public class Outer {
//成员内部类
class Inner{ }
// 成员方法
public void method(){
// 局部内部类
class Inner2{ }
}
}
一、成员内部类:
定义在外部类的成员位置。可以使用成员修饰符public static、可以继承、实现接口。
访问方式:
1、在外部类提供一个方法创建内部类的对象进行访问。
2、在其他类中直接创建内部类的对象。Outer.Inner inner = new Outer().new Inner();
public class Outer {
//成员变量
int x = 93;
int y = 84;
//成员内部类
public class Inner{
int i = 10;
int x = 26; // 存在同名的成员变量默认访问的是外部类的变量, Outer.this.x 访问外部同名变量
public void print(){
System.out.println("内部类中访问 x:"+ x); // 26
System.out.println("内部类中访问 x:"+ Outer.this.x); // 93
System.out.println("内部类中访问 y:"+ y); // 84
}
}
// 成员内部类出现了静态成员,该类必须使用static修饰
public static class Inner2{
static String name = "ron";
public void heart(){
System.out.println("The one: " + name);
}
}
//在外部的方法中创建了内部类的对象,然后调用内部 方法。
public void instance(){
Inner inner = new Inner();
inner.print();
}
}
// 测试
public class Demo {
public static void main(String[] args) {
// 访问内部类的方式一
Outer outer = new Outer();
outer.instance();
// 访问内部类的方式二
Outer.Inner inner = new Outer().new Inner();
inner.print();
// 访问静态的内部类
Outer.Inner2 inner2 = new Outer.Inner2();
inner2.heart(); // The one: ron
String name = Outer.Inner2.name;
}
}
注意细节:
1、内部类可以直接访问外部类的成员,包括私有成员。如上:访问变量 y。
2、外部类与内部类存在同名的成员变量时,内部类中默认访问的是内部类中的成员变量,可通过: 外部类·this·成员变量,指定访问外部类中的成员。如上:访问变量 x。
3、私有的成员内部类只能在外部类中提供一个方法创建内部类的对象进行访问(即方式一)。
4、成员内部类一旦出现了静态的成员,那么该类也必须使用static修饰。
5、静态的内部类访问方式:如上。
面试题:
class Outer {
int i = 1;
class Inner {
int i = 2;
public void heart(){
int i = 3;
System.out.println("i的值:" + i);// 3
System.out.println("i的值:" + this.i);// 2
System.out.println("i的值:" + Outer.this.i);// 1
}
}
}
二、局部内部类:
在一个类的方法中定义另外一个类。
访问: 外部类的方法中创建内部类对象,进行访问。
public class Outer2 {
String name = "ron";
public void heart() {
// 局部变量
final int y = 100;
// 局部内部类
class Inner {
int x = 10;
public void print() {
System.out.println("局部内部类方法: " + y);
}
}
Inner inner = new Inner();
inner.print();
}
}
// 测试:
public class Demo {
public static void main(String[] args) {
new Outer2().heart();
}
}
注意细节:
1、局部内部类只能访问所在函数的fanal属性。
使用final的原因:
案例中的heart() 方法、print() 方法之间的数据不能共享,可使用static、final实现共享,但static不能修饰局部变量。加final后将y 放到了方法区中的常量池中共享。而在print方法中调用的只是y 的复制品,heart() 方法执行完毕后 y 才消失。
三、匿名内部类:
没有内名的内部类,注意:匿名内部类只是没有类名,其他的一概成员都是具备的。
使用前提: 一个类(抽象、非抽象)、接口。
new Thread(
() -> {
System.out.println("RRRRROOOOONNNNN");
}
).start();
// 实现关系下的匿名内部类:
interface Dao {
void add();
}
public class Outer3 {
public void heart(){
// 接口关系下的匿名内部类
new Dao(){
@Override
public void add() {
System.out.println("接口方法...");
}
}.add();
}
}
// 测试:
public class Demo {
public static void main(String[] args) {
Outer3 outer3 = new Outer3();
outer3.heart();
}
}
匿名内部类可用于给方法传递实参,
public class Demo {
public static void main(String[] args) {
test(new Dao() {
@Override
public void add() {
System.out.println("匿名内部类用于方法实参");
}
});
}
private static void test(Dao d) {
d.add();
}
}