N种内部类

内部类

1.内部类概述

内部类就是在一个类的内部在定义一个类,比如,A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。

内部类不是在一个java源文件中编写俩个平行的俩个类,而是在一个类的内部再定义另外一个类。 我们可以把外边的类称为外部类,在其内部编写的类称为内部类。

内部类分为四种:

  1. 成员内部类

  2. 静态内部类

  3. 局部内部类

  4. 匿名内部类

2.成员内部类(实例内部类、非静态内部类

注:成员内部类中不能写静态属性和方法

【定义一个内部类】

//在A类中申明了一个B类,此B类就在A的内部,并且在成员变量的位置上,所以就称为成员内部类 
public class Outer { 
    private int id; 
    public void out(){ 
        System.out.println("这是外部类方法"); 
    }
    
    class Inner{ 
        public void in(){ 
            System.out.println("这是内部类方法"); 
        } 
    } 
}

【实例化内部类】

实例化内部类,首先需要实例化外部类,通过外部类去调用内部类

public class Outer { 
    private int id; 
    public void out(){ 
        System.out.println("这是外部类方法"); 
    }
    
    class Inner{ 
        public void in(){ 
            System.out.println("这是内部类方法"); 
        } 
    } 
}

public class Test{ 
    public static void main(String[] args) { 
        //实例化成员内部类分两步 
        //1、实例化外部类 
        Outer outObject = new Outer(); 
        //2、通过外部类调用内部类 
        Outer.Inner inObject = outObject.new Inner(); 
        //测试,调用内部类中的方法
        inObject.in();//打印:这是内部类方法 
    } 
}

分析:想想如果你要使用一个类中方法或者属性,你就必须要先有该类的一个对象,同理,一个类在另一个类的内部,那么想要使用这个内部类,就必须先要有外部类的一个实例对象,然后在通过该对象去使用内部类。

【成员内部类能干什么?】

  1. 访问外部类的所有属性(这里的属性包括私有的成员变量,方法)
public class Outer { 
    private int id; 
    public void out(){ 
        System.out.println("这是外部类方法"); 
    }
    
    class Inner{ 
        public void in(){ 
            System.out.println("这是内部类方法"); 
        }
        
        //内部类访问外部类私有的成员变量 
        public void useId(){ 
            System.out.println(id+3); 
        }
        
        //内部类访问外部类的方法 
        public void useOut(){ 
            out(); 
        } 
    } 
}

public class Test{ 
    public static void main(String[] args) { 
        //实例化成员内部类分两步 
        //1、实例化外部类 
        Outer outObject = new Outer(); 
        //2、通过外部类调用内部类 
        Outer.Inner inObject = outObject.new Inner(); 
        //测试 inObject.useId();//打印3,因为id初始化值为0,0+3就为3,其中在内部类就使用了 外部类的私有成员变量id。 
        inObject.useOut();//打印:这是外部类方法 
    } 
}
  1. 如果内部类中的变量名和外部类的成员变量名一样,要通过创建外部类对象 "."属性来访问外部类属性,通过this.属性访问内部类成员属性
public class Outer { 
    private int id;//默认初始化0 
    public void out(){ 
        System.out.println("这是外部类方法"); 
    }
    class Inner{ 
        private int id=8; //这个id跟外部类的属性id名称一样。 
        public void in(){ 
            System.out.println("这是内部类方法"); 
        }
        
        public void test(){ 
            System.out.println(id);//输出8,内部类中的变量会暂时将外部类的成员 变量给隐藏 
            //如何调用外部类的成员变量呢?通过Outer.this,想要知道为什么能通过这个 来调用,就得明白下面这个原理 //想实例化内部类对象,就必须通过外部类对象,当外部类对象来new出内部类对 象时,会 
            //把自己(外部类对象)的引用传到了内部类中,所以内部类就可以通过 Outer.this来访问外部类的属性和方法,到这里,你也就可以知道为什么内部类可以访问外部类 的属性和方法,这里由于有两个相同的 
            属性名称,所以需要显示的用Outer.this来调用外部类的属性,平常如果属性名 不重复,那么我们在内部类中调用外部类的属性和方法时,前面就隐式的调用了Outer.thisSystem.out.println(Outer.this.id);//输出外部类的属性id。也 就是输出0 
        } 
    }
}

借助成员内部类,来总结内部类(包括4种内部类)的通用用法:

1、要想访问内部类中的内容,必须通过外部类对象来实例化内部类。

2、能够访问外部类所有的属性和方法,原理就是在通过外部类对象实例化内部类对象时,外部类对象把自己的引用传进了内部类,使内部类可以用通过Outer.this去调用外部类的属性和方法,

一般都是隐式调用了,但是当内部类中有属性或者方法名和外部类中的属性或方法名相同的时候,就需要通过显式调用Outer.this了。

【写的一个小例子】

public class MemberInnerClassTest { 
    private String name; 
    private static int age; 
    
    public void run(){} 
    
    public static void go(){} 
    
    public class MemberInnerClass{ 
        private String name; 
        
        //内部类访问外部类 
        public void test(String name){ 
            System.out.println(name); 
            System.out.println(this.name); 
            System.out.println(MemberInnerClassTest.this.name); 
            System.out.println(MemberInnerClassTest.age); 
            MemberInnerClassTest.this.run(); 
            MemberInnerClassTest.go(); 
        } 
    }
    //外部类访问成员内部类 
    //成员内部类的对象要 依赖于外部类的对象的存在 
    public void test(){ 
        //MemberInnerClass mic = MemberInnerClassTest.this.new 
        MemberInnerClass(); 
        //MemberInnerClass mic = this.new MemberInnerClass(); 
        MemberInnerClass mic = new MemberInnerClass(); mic.name = "tom"; 
        mic.test("hua"); 
    }
    
    public static void main(String[] args) { 
        //MemberInnerClass mic = new MemberInnerClass();这个是不行的,this是动态的。 
        //所以要使用要先创建外部类对象,才能使用 
        MemberInnerClassTest out = new MemberInnerClassTest(); 
        MemberInnerClass mic = out.new MemberInnerClass(); 
        //如果内部类是private,则不能访问,只能铜鼓内部方法来调用内部类 
        mic.name="jik"; 
        mic.test("kkk"); 
    } 
}

3.静态内部类

看到名字就知道,使用你static修饰的内部类就叫静态内部类。

既然提到了static,那我们就来复习一下它的用法:一般只修饰变量和方法,平常不可以修饰类,但是内部类却可以被static修饰。

1)static修饰成员变量:整个类的实例共享静态变量

2)static修饰方法:静态方法,只能够访问用static修饰的属性或方法,而非静态方法可以访问static修饰的方法或属性

3)被static修饰了的成员变量和方法能直接被类名调用。

4)static不能修饰局部变量,切记,不要搞混淆了,static平常就用来修饰成员变量和方法。

写了一个例子,可以给大家看一下:

public class StaticInnerClassTest { 
    private String name; 
    private static int age; 
    
    public void run(){} 
    
    public static void go(){} 
    
    //外部类访问静态内部类 
    public void test(){ 
        StaticInnerClass sic = new StaticInnerClass(); //静态的内部类不需要依赖 外部类,所以不用this 
        sic.name = "tom";
        sic.test1("jack"); 
        
        StaticInnerClass.age=10; 
        StaticInnerClass.test2("xixi"); 
    
    }
    private static class StaticInnerClass{ 
        private String name; 
        private static int age; 
        public void test1(String name){ 
            System.out.println(name); 
            System.out.println(this.name); 
            System.out.println(StaticInnerClass.age); 
            
            System.out.println(StaticInnerClassTest.age); 
            //System.out.println(StaticInnerClassTest.this.name);静态类不能访问非静态属性 
            StaticInnerClassTest.go(); 
            //StaticInnerClassTest.this.run();静态类不能访问非静态方法 
        }
        public static void test2(String name){ 
            //只能访问自己和外部类的静态属性和方法 
            System.out.println(name); 
            //System.out.println(this.name);静态方法里面连自己类的非静态属性都不能访问 
            System.out.println(StaticInnerClass.age); 
            
            System.out.println(StaticInnerClassTest.age); 
            //System.out.println(StaticInnerClassTest.this.name);静态方法不能访问非静态属性 
            StaticInnerClassTest.go(); 
            //StaticInnerClassTest.this.run();静态方法不能访问非静态方法 
        } 
        
    } 
}

注意:

1、我们上面说的内部类能够调用外部类的方法和属性,在静态内部类中就行了,因为静态内部类没有了指向外部类对象的引用。除非外部类中的方法或者属性也是静态的。这就回归到了static关键字的用法。

2、静态内部类能够直接被外部类给实例化,不需要使用外部类对象

Outer.Inner inner = new Outer.Inner();

3、静态内部类中可以声明静态方法和静态变量,但是非静态内部类中就不可以声明静态方法和静态变量

4.局部内部类

局部内部类是在一个方法内部声明的一个类

局部内部类中可以访问外部类的成员变量及方法

局部内部类中如果要访问该内部类所在方法中的局部变量,那么这个局部变量就必须是final修饰的

public class Outer { 
    private int id; 
    //在method01方法中有一个Inner内部类,这个内部类就称为局部内部类 
    public void method01(){class Inner{ 
        public void in(){ 
            System.out.println("这是局部内部类"); 
        } 
    } 
  } 
}

5.匿名内部类

在这四种内部类中,以后的工作可能遇到最多的是匿名内部类,所以说匿名内部类是最常用的一种内部类。

什么是匿名对象?如果一个对象只要使用一次,那么我们就是需要new Object().method()。 就可以了,而不需要给这个实例保存到该类型变量中去。这就是匿名对象。

public class Test { 
    public static void main(String[] args) { 
        //讲new出来的Apple实例赋给apple变量保存起来,但是我们只需要用一次,就可以这样写 
        Apple apple = new Apple(); 
        apple.eat(); 
        //这种就叫做匿名对象的使用,不把实例保存到变量中。 
        new Apple().eat(); 
    } 
}
class Apple{ 
    public void eat(){ 
        System.out.println("我要被吃了"); 
    } 
}

匿名内部类跟匿名对象是一个道理:

匿名对象:我只需要用一次,那么我就不用声明一个该类型变量来保存对象了,

匿名内部类:我也只需要用一次,那我就不需要在类中先定义一个内部类,而是等待需要用的时候,我就在临时实现这个内部类,因为用次数少,可能就这一次,那么这样写内部类,更方便。不然先写出一个内部类的全部实现来,然后就调用它一次,岂不是用完之后就一直将其放在那,那就没必要那样。

  1. 匿名内部类需要依托于其他类或者接口来创建
  • 如果依托的是类,那么创建出来的匿名内部类就默认是这个类的子类

  • 如果依托的是接口,那么创建出来的匿名内部类就默认是这个接口的实现类。

  1. 匿名内部类的声明必须是在使用new关键字的时候
  • 匿名内部类的声明及创建对象必须一气呵成,并且之后能反复使用,因为没有名字。

【示例】

A是一个类(普通类、抽象类都可以),依托于A类创建一个匿名内部类对象

main: 

A a = new A(){ 
    //实现A中的抽象方法 
    //或者重写A中的普通方法 
};:这个大括号里面其实就是这个内部类的代码,只不过是声明该内部类的同时就是要new创建了其对象, 并且不能反复使用,因为没有名字。 
    
例如: 
B是一个接口,依托于B接口创建一个匿名内部类对象 
    
    B b = new B(){ 
    //实现B中的抽象方法 
};
  1. 匿名内部类除了依托的类或接口之外,不能指定继承或者实现其他类或接口,同时也不能被其他类所继承,因为没有名字。

  2. 匿名内部中,我们不能写出其构造器,因为没有名字。

  3. 匿名内部中,除了重写上面的方法外,一般不会再写其他独有的方法,因为从外部不能直接调用到。(间接是调用到的)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值