java 内部类 笔记

内部类

- 定义:

定义在一个类里面或者一个方法里面的类,即为内部类。

- 内部类的作用:

1、每个内部类都能独立地继承自某个类或实现某个接口,无论外部类是否继承了某个类或实现某个接口。这个特性使得多重继承成为可能。(例如外部类A中包括继承了B类的内部类C,C类拥有B类的方法,A类拥有C类的方法,所以A类拥有B、C类的方法,相当于多继承)
2、内部类可以很好的实现隐藏,我们控制类的访问权限,是通过类前面的访问修饰符来限制的,一般的非内部类,是不允许有 private 与protected权限的,但内部类可以,所以我们能通过内部类来隐藏我们的信息
3、可以避免修改接口而实现同一个类中两种同名方法的调用。假如一个类要继承一个类,还要实现一个接口,但是要继承的类和接口中由方法名字相同,此时没有办法区分这两个方法,就需要内部类。

- 注意:内部类和外部类之间属性的互相访问,需要通过对象来访问。

- 内部类的种类:

基本上有四种:静态内部类、成员内部类、局部内部类、匿名内部类。
  • 1、静态内部类

     定义在类内部的静态类,就是静态内部类。语法如下:
    
    public class Out {
        public static int age;
        public String name;
    
        public static class Inner {
        	public void sleep(){
        	
    		}
        }
    }
    

    说明:

    1、静态内部类可以访问外部类所有的静态变量和方法(包括使用 private 修饰的),但是不能访问外部类的普通变量和方法。和静态方法、静态变量类似,静态内部类在加载的时候就已经创建,不需要依赖外部类的实例,使用静态内部类时,外部类的实例还不一定被声明出来,所以静态内部类不能调用外部类的普通变量和方法。
    2、静态内部类可以有自己的静态变量、方法,构造方法等。
    3、静态内部类的优点是:外部类加载时并不需要立即加载内部类。

    其它类使用静态内部类需要使用 “外部类.静态内部类” 方式,如下:

    Out.Inner inner = new Out.Inner();
    inner.sleep();
    
  • 2、成员内部类

     定义在类内部的非静态类,就是成员内部类。语法如下:
    
    public class Outer {
        private static int age;
        private String name;
    
        public class Inner {
            public void sleep() {
            
            }
        }
    }
    

    说明:

    1、内部类中不能定义静态成员和方法,因为内部类是外部类的一个成员,只有当外部类初始化时,内部类才能初始化,静态变量属于类级别,在类加载的时候就初始化,所以两者本身在语法上就有矛盾。但可以定义常量,常量是存放在常量池中的,不涉及到类的加载。
    2、成员内部类可以访问外部类所有的变量和方法,包括静态和实例,私有和非私有。和静态内部类不同的是,每一个成员内部类的实例都依赖一个外部类的实例。其它类使用内部类必须要先创建一个外部类的实例,创建内部类实例有如下两种方法:

    方法一(需要在外部类中设置一个方法,用于返回一个内部类对象):

    	
    public class Outer {
     
        private Inner getInner() {
            return new Inner();
        }
     
        public class Inner{}
    }
    
    	//如果你想创建某个内部类对象,必须在 new 表达式中提供其外部类的引用,这时需要使用 .new 语法
    	Outer outer = new Outer();
    	Outer.Inner inner = outer.new Inner();
    	inner.sleep();
    

    方法二

    	Outer outer = new Outer();
    	Outer.Inner inner = out.getInner()
    	inner.sleep();
    

    成员内部类访问外部类:

    成员内部类可以访问外部类的所有成员变量和成员方法(包括private成员和静态成员)。如果要在内部类中生成外部类对象的引用,可以使用 外部类名.this
    例如:

    public class Outer {
        
        public class Inner {
            public Outer getOuter() {
                return Outer.this;
            }
        }
        
        public static void main(String[] args) {
              Outer outer = new Outer();
    		//Outer.Inner inner = outer.new Inner();
       		  Outer.Inner inner = outer.getInstance();
              Outer outer1 = inner.getOuter();
        }
    }
    

    当成员内部类拥有和外部类同名的成员变量或者方法时,会发生隐藏现象,即内部类中如果调用或者访问同名变量、同名方法,默认访问的是成员内部类的成员。如果在内部类中要访问外部类的同名成员,需要以下面的形式进行访问:

    外部类.this.成员变量
    外部类.this.成员方法
    

    例如:

    package neibulei;
    
    /**
     * Created by joker on 2022/1/5.
     */
    public class Outer {
        int age =1;
        String name ="waibulei";
    
        void printName(){
            System.out.println("waibulei");
        }
    
        public Inner getInstance(){
            return new Inner();
        }
    
        public class Inner{
            public int age=2;
            String name ="neibulei";
    
            void printName(){
                System.out.println("neibulei");
            }
    
            void printn(){
                System.out.println(age);
                System.out.println(name);
            }
    
            void printw(){
                System.out.println(Outer.this.age);
                System.out.println(Outer.this.name);
            }
        }
    }
    
    
    package neibulei;
    
    /**
     * Created by joker on 2022/1/5.
     */
    public class test {
        public static void main(String[] args) {
            Outer outer = new Outer();
    		//Outer.Inner inner= outer.new Inner();
            Outer.Inner inner = outer.getInstance();
    
            inner.printn();
            inner.printName();
        }
    }
    
    

    外部类访问成员内部类的属性:

    外部类可以访问内部类的所有成员变量和方法(包括private),但外部类想访问成员内部类的成员,必须先创建一个成员内部类的实例,再通过这个实例去点属性、方法来访问。

  • 3、局部内部类:

      局部内部类是定义在一个方法或代码块里面的类。
    

    语法格式:

    public class Outer {
        
        public void testFangfa() {
            class Inner {
                ...
            } 
        }
    }
    

    例如:

    package neibulei;
    
    /**
     * Created by joker on 2022/1/5.
     */
    public class juBuNeiBuLei {
        public void juBuNeiBuLei(){
            class ceShi{
                public int a =1;
                public String b ="局部内部类";
                
                public void print(){
                    System.out.println("局部内部类的方法");
                }
            }
        }
    }
    
    

    注:
    1、局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

    2、局部内部类不可以定义静态成员和方法。
    3、局部类只能在定义该局部类的方法中使用。定义在实例方法中的局部内部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法。局部类还可以访问其所在方法内的常量。

  • 4、匿名内部类:

    1、定义:没有名字的内部类(包括没有名字的成员内部类和局部内部类),需要使用实例化对象的形式来创建。
    2、使用匿名内部类的前提和条件:必须存在继承或实现关系的时候才可以使用。因为匿名内部类没有名字,所以要通过继承父类或者实现接口的形式来创建对象,同时extends和implements也不会显示体现,而是由jvm操作。
    3、匿名内部类的对象,通过 new 表达式返回的这个引用被自动向上转型为 父类的引用。
    4、匿名内部类没有构造器(因为它没有名字),如果需要为匿名内部类做一些初始化操作,如果该匿名内部类的基类构造器有参数,则可以直接使用,但编译器会要求其参数引用是 final(即使你不加,Java8 也会为我们自动加上 final)。或者通过代码块,模仿构造器的行为来实现初始化。
    5、匿名内部类访问外部类属性的权限,需要看这个匿名内部类是成员内部类还是局部内部类,具体来看。

    语法格式:

    //这个 new 开始就是匿名内部类,正常是: 类名 引用名 = new 类名() ,匿名内部类只有 “=” 右边的部分,如下:
    new 父类名或接口名(){	
    	       //匿名内部类的具体实现,重写父类方法或者实现接口的方法。
    };
    //说明:如果 new 后面的是接口名,此处并不是直接实例化接口,因为java中接口不能实例化,但可以被实现,此处是匿名内部类实现此接口并且自动向上转型,所以这么写没问题。
    

    例如:

    package neibulei;
    
    /**
     * Created by joker on 2022/1/6.
     */
    public class niMingNeiBuLei {
        public int age = 1;
        public String name = "god";
    
        //匿名局部内部类,此处继承了Object类,此处还可以是实现接口的方式
        Object object = new Object(){
            int a = 2;
            String n = "s";
    
            @Override
            public String toString() {
                return super.toString();
            }
        };
    
        //匿名成员内部类,此处继承了Object类,此处还可以是实现接口的方式
        void run(){
            Object object = new Object(){
              int b = 3;
              String m = "x";
    
                @Override
                public String toString() {
                    return super.toString();
                }
            };
        }
    }
    
    

    匿名内部类可以作为实参使用。

    如何继承内部类?待补充

    一个java类中可以有多个 class,但只能有一个 public class。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值