(本质上可以理解为一个类的局部位置比如方法里面的局部变量,只不过是类罢了)
public class outer {
private int n1 = 10;//外部类的私有属性
public void m1(){//外部类的一个方法
class inner{//在这个方法内部创建了一个局部内部类
public void innerWay(){//在这个局部内部类里可以调用外部类的所有成员包括私有的
System.out.println(n1);
}
}
}
}
本质上可以理解为一个类的局部位置比如方法里面的局部变量,只不过是类罢了,所以它有局部变量的特点(不能用修饰符修饰,final除外),同时兼顾类的继承特点
class a{};
public class outer {
private int n1 = 10;//外部类的私有属性
public void m1(){//外部类的一个方法
class inner{//在这个方法内部创建了一个局部内部类
public void innerWay(){//在这个局部内部类里可以调用外部类的所有成员包括私有的
System.out.println(n1);
}
}
class inner2 extends inner{};
}
}
因为是局部变量,所以它的作用范围也只能定义它的代码块当中,如下,同一个外部类里面方法2的局部内部类是不能继承方法1的局部内部类的
public class outer {
private int n1 = 10;//外部类的私有属性
public void m1(){//外部类的一个方法
class inner{//在这个方法内部创建了一个局部内部类
public void innerWay(){//在这个局部内部类里可以调用外部类的所有成员包括私有的
System.out.println(n1);
}
}
class inner2 extends inner{};//同一个代码块的可以继承
}
public void m2(){
class inner3 extends inner//因为局部内部类是局部变量
// 所以不能继承另一个代码块里的局部内部类
}
}
外部类通过在方法体中创建局部内部类的实例化 调用局部内部类成员 的成员,然后在主方法中创建外部类的实例,调用,方法,方法里有内部类的实例,然后内部类的实例最后调用内部类的
public class outer {
private int n1 = 10;//外部类的私有属性
public void m1() {//外部类的一个方法
class inner {//在这个方法内部创建了一个局部内部类
public void innerWay() {//在这个局部内部类里可以调用外部类的所有成员包括私有的
System.out.println(n1);
}
}
inner Inner = new inner();//在局部内部类存在的方法或代码块内创建其对象
// 再调用它你想要调用的方法,就可以完成对其的访问
Inner.innerWay();
}//m1方法的花括号
}
就是在局部内部类存在的那个方法或者代码块里创建它的对象,再实现对它方法的调用
public class t {
public static void main(String[] args) {
outer outer = new outer();
outer.m1();
}
}
如果局部内部类有属性和外部类重名,这在该方法里的访问是就近原则直接访问局部内部类的属性,如果要访问外部类的属性,需要:外部类.this.属性名,的方法访问
public class outer {
private int n1 = 10;//外部类的私有属性
public void m1() {//外部类的一个方法
class inner {//在这个方法内部创建了一个局部内部类
public int n1 = 100;
public void innerWay() {
System.out.println(n1);
}
}
System.out.println(n1);//访问的是内部类的n1 = 100
System.out.println(outer.this.n1);//访问的是外部类的n1 = 10
}//m1方法的花括号
}
而对于重名的方法,直接调用是外部类的方法,而内部类的方法调用需要创建对象去访问
局部内部类本质上同时有局部变量和类的特点
注意:匿名内部类一般定义在局部位置(方法内),也可以直接定义在成员位置
public class outer {
IG ig = new IG() {
@Override
public void use() {
System.out.println("ig在使用");
}
};//我们知道接口是不能实例化的,但是作为匿名内部类的运行机制
// 这里的底层系统给我们分配了一个系统创建名字的类去完成该接口的实现
//然后把这个类的地址返回给我们的引用对象
// 然后可以理解系统创建的那个模板(类)没有了,但是对象还在
IG ig2 = new IG() {//这里等于是底层创新又定义一个类,
//我们重新实现接口后,类销毁,地址返回给这个ig2的引用对象
@Override
public void use() {
System.out.println("ig2在使用");
}
};
public void way(){
ig.use();
ig2.use();
}
}
interface IG{
void use();
}
我们知道接口是不能实例化的,但是作为匿名内部类的运行机制,这里的底层系统给我们分配了一个系统创建名字的类去完成该接口的实现 ,然后把这个类的地址返回给我们的引用对象,然后可以理解系统创建的那个模板(类)没有了,但是对象还在。
package learn;
public class outer {
Animal animal = new Animal(){
public int a = 100;//自己创建的属性
public void eat(){//对父类方法的重写
System.out.println(age);
System.out.println(a);//调用自己创建的属性
sleep();//调用自己创建的方法
}
public void sleep(){
System.out.println("sleep");
}
};
public void method(){
animal.eat();//调用匿名内部对象的方法
}
}
class Animal{//父类
public int age = 10;
static {
System.out.println("静态代码块");
}//父类的静态代码块,加载的时候会显示
public void eat(){
System.out.println("Animal");
}
}
作为匿名内部类的运行机制,这里的底层系统给我们分配了一个系统创建名字的子类去继承父类(我们等号左的那个类)(这个时候也会完成父类的加载)然后把这个子类的地址返回给我们的引用对象,然后可以理解系统创建的那个模板(类)没有了,但是对象还在。(这种比较类似于向上转型,我们只能直接调用编译类型的属性和方法(当然可以重写,也可以创建这个类的其它方法和属性,最后在重写的方法里面体现出来))
当然如果继承的是抽象类,就必须重写他的方法
匿名内部类一般定义在局部位置(方法内),也可以直接定义在成员位置,如果定义在局部位置,就是局部变量,才遵循第四点,与第五点
对于第六点:
class outer {
class inner{
public void say(){
System.out.println("我在说话");
}
}
}
public class t {
public static void main(String[] args) {
outer out = new outer();//创建一个外部类的对象
outer.inner one = out.new inner();//用这个对象创建内部类的对象
}
}
还可以直接创建:
outer.inner one = new outer().new inner();//直接创建
class outer {
class inner{
public void say(){
System.out.println("我在说话");
}
}
public inner getinner(){
return new inner();//在外部类创建一个方法,返回内部类
}
}
public class t {
public static void main(String[] args) {
outer out = new outer();//创建一个外部类的对象
outer.inner one = out.getinner();//用这个对象的方法返回成员内部类
}
}
与局部内部类差别在所处的位置。所以在作用域和修饰符方面,成员内部类更包容一些,而对于类的特点,没有改变(也有属性,构造器,方法,内部类,代码块),可以继承,与实现接口,并且外部其他类可以访问成员内部类
对于第六点
在成员内部类的基础上增加了静态的调用机制
class outer {
static class inner{
public void say(){
System.out.println("我在说话");
}
}
public inner getinner(){
return new inner();//在外部类创建一个方法,返回内部类
}
public static inner getStaticinner(){
return new inner();//在外部类创建静态方法返回对象
}
}
public class t {
public static void main(String[] args) {
outer.inner one = new outer.inner();//直接调用静态成员来创建
outer.inner two = outer.getStaticinner();//调用静态方法返回
outer.inner three = new outer().getinner();//创建外部类的一个对象后调用成员方法
}
}
在成员内部类的基础上增加了静态的属性,导致在访问时,有静态的特点,和在外部其他类创建静态局部类时,略有不同