概念:一个类的内部又完整的嵌套了另一个类结构,被嵌套的类称为内部类,嵌套其他类的类称为外部类
语法:class Outer{ class Inner{}//内部类 }//外部类
public class Study {//外部其他类
public static void main(String[] args) {
}
}
class Outer{//外部类
private int n1=100;//属性
public void say(){//方法
System.out.println("Outer say()");
}
public Outer(int n1) {//构造器
this.n1 = n1;
}
{//代码块
System.out.println("Outer {}");
}
class Inner{//内部类
}
}
内部类的分类:
定义在外部类局部位置上(比如方法内):
(1)局部内部类(有类名)
概念:局部内部类是定义在外部类的局部位置,比如方法中,并且有类名
注意事项:
a、可以直接访问外部类的所有成员,包含私有的
b、不能添加访问修饰符,因为它的地位就是一个局部变量,局部变量是不能使用修饰符的。但是可以使用final修饰,因为局部变量也可以用final
c、作用域:仅仅在定义它的方法或代码块中
d、局部内部类->访问->外部类的成员(访问方式:直接访问)
e、外部类->访问->局部内部类的成员(访问方式:创建对象,再访问;必须在作用域内)
f、如果外部类和成员内部类的成员重名时,内部类访问的话,默认遵循就近原则,如果想要访问外部类的成员,则可以使用(外部类类名.this. 成员)去访问
public class Study {
public static void main(String[] args) {
Outer outer = new Outer();
outer.m1();
}
}
class Outer{
private int n1=10;
private void m2(){
System.out.println("Outer m2()");
}
public void m1(){
//局部内部类是定义在外部类的局部位置,通常在方法中
class Inner{//局部内部类
//可以直接访问外部类的所有成员,包含私有的
public void f1(){
System.out.println("n1="+n1);
m2();
}
}
//外部类在方法中,可以创建Inner对象,然后调用Inner中的方法
new Inner().f1();
}
}
f、外部其他类---不能访问-->局部内部类
g、如果外部类和局部内部类的成员重名时,默认遵循就近原则,如果想访问外部类的成员,则可以使用(外部类名.this.成员)去访问
public void f1(){
System.out.println("n1="+n1);
m2();//Inner类中的m2方法
Outer.this.m2();//Outer类中的m2方法
//Outer.this本质就是外部类的对象
}
(2)匿名内部类(没有类名)//重点
概念:匿名内部类是定义在外部类的局部位置,并且没有类名
语法:new 类或接口(参数列表){ 类体 };// ; 不能省略
//基于接口的匿名内部类
class Outer{
public void m1(){
//a的编译类型是A
//a的运行类型就是匿名内部类
//jdk在底层创建匿名内部类后,立即创建一个对象实例,并把地址返回给a
//会完成以下步骤
/*class 系统分配类名 implements A{
public void say(){
System.out.println();
}
}
*/
A a = new A(){
@Override
public void say() {}
};
System.out.println(a.getClass());//得到a的运行类型
}
}
interface A{
public void say();
}
//基于类的匿名内部类
class Outer{
public void m1(){
//father编译类型是Father
//father运行类型是匿名内部类
/* 底层会进行如下操作
class 系统分配类名 extends Father{}
*/
Father father = new Father("jack"){
};
System.out.println(father.getClass());
}
}
class Father{
private String name;
public Father(String name) {
this.name = name;
}
}
匿名内部类的最佳实践:
a、当作实参直接传递,简洁高效
public class Study {
public static void main(String[] args) {
m1(new A() {
@Override
public void say() {
System.out.println("who");
}
});
}
public static void m1(A a){
a.say();
}
}
interface A{
void say();
}
定义在外部类的成员位置上:
(1)成员内部类(没有static修饰)
概念:成员内部类是定义在外部类的成员位置,并且没有static修饰
a、可以直接访问外部类的所有成员,包含私有的
b、可以添加任意的访问修饰符
c、作用域:和外部类的其他成员一样,为整个类体
d、成员内部类---访问--->外部类(访问方式:直接调用)
e、外部类---访问--->成员内部类(访问方式:创建对象,再访问)
f、外部其它类---访问--->成员内部类(访问方式:间接创建对象,外部类方法返回内部类对象)
public class Study {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.show();
}
}
class Outer{
private int n1=10;
public class Inner{
private int n2=20;
public void show(){
System.out.println("n1="+n1);
}
}
public void Create(){
Inner inner = new Inner();
inner.show();
System.out.println(inner.n2);
}
}
(2)静态内部类(使用static修饰)
概念:静态内部类是定义在外部类的成员位置,并且有static修饰
a、可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
b、可以添加任意的访问修饰符
c、作用域:同其他的成员,为整个类体
d、静态内部类---访问--->外部类(直接访问所有静态成员)
e、外部类---访问--->静态内部类(创建对象,再访问)