zoukankan      html  css  js  c++  java
  • 内部类

    匿名内部类

    匿名内部类使用注意事项

    • 匿名内部类也就是没有名字的内部类
    • 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代 码编写
    • 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接 口 匿名
    • 内部类中是不能定义构造函数的

    使用的形参为何要为final

    1. 我们给匿名内部类传递参数的时候,若该形参在内部类中需要被使 用,那么该形参必须要为final。也就是说:当所在的方法的形参需要 被内部类里面使用时,该形参必须为final。

    为什么必须要为final呢

    • 首先我们知道在内部类编译成功后,它会产生一个class文 件,该class文件与外部类并不是同一class文件,仅仅只保 留对外部类的引用。当外部类传入的参数需要被内部类调 用时,从java程序的角度来看是直接被调用
    • 在内部类中的属性和外部方法的参数两者从外表上看是同 一个东西,但实际上却不是,所以他们两者是可以任意变 化的,也就是说在内部类中我对属性的改变并不会影响到 外部的形参,而然这从程序员的角度来看这是不可行的, 毕竟站在程序的角度来看这两个根本就是同一个,如果内 部类该变了,而外部方法的形参却没有改变这是难以理解 和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不可改变
    • 简单理解就是,拷贝引用,为了避免引用值发生改变,例 如被外部类的方法修改等,而导致内部类得到的值不一 致,于是用final来让该引用不可改变。
    • 故如果定义了一个匿名内部类,并且希望它使用一个其外 部定义的参数,那么编译器会要求该参数引用是final的

    匿名内部类初始化

    我们一般都是利用构造器来完成某个实例的初始化工作的,但是匿名内部类是没 有构造器的!那怎么来初始化匿名内部类呢?使用构造代码块!利用构造代码块 能够达到为匿名内部类创建一个构造器的效果

    常见的匿名内部类实例

    public class Demo {
    	public static void main(String[] args) {
    		Runnable r = new Runnable() {
    			public void run() {
    				for (int i = 1; i <= 5; i++) {
    					System.out.print(i + " ");
    				}
    			}
    		};
    		Thread t = new Thread(r);
    		t.start();
    	}
    }
    
    

    Java内部类小结

    成员内部类 也是最常规的内部类。该内部类相当于位于外部类的成员的位置。该内部类可以 访问外部类的所有成员和方法,即使是private.

    public class Outer {
    	public class Inner {
    		public void print(String str) {
    			System.out.println(str);
    		}
    	}
        
    	public Inner getInner() {
    		return new Inner();
    	}
        
    	public static void main(String[] args) {
    		Outer outer = new Outer();
    		Outer.Inner inner = outer.new Inner();
    		inner.print("Outer.new");
            
    		inner = outer.getInner();
    		inner.print("Outer.get");
    	}
    }
    
    

    静态内部类

    1. 该类被修饰为static。同时作为静态内部类,他不能访问外部类非静态 的成员或方法。
    2. 访问方式如上所述。
    3. 一般书写静态类时,不涉及成员变量。
    class Outter {
    	public Outter() {
    		System.out.println("Outter constructor.");
    	}
    	static class Inner {
    		public Inner() {
    			System.out.println("Inner constructor.");
    		}
    	}
    }
    public class Test {
    	public static void main(String[] args) {
    		Outter.Inner inner = new Outter.Inner();
    	}
    }
    
    

    方法内部类 类被创建在外部类方法中

    1. 可以访问外部类中的成员
    2. 不能被static private 修饰,因为他不再是成员位置,只有成员才能被 修饰为static...
    3. 因此内部类不能有静态成员
    4. 内部类要访问外部方法中的局部变量时,该局部变量需要被修饰成final
    class People{
    	public People() {
    	}
    }
    class Man{	
    	public Man(){
    	}
    	public People getWoman(){
    		class Woman extends People{ //局部内部类
    			int age =0;
    		}
    		return new Woman();
    	}
    }
    

    匿名内部类

    1. 就是一个内部类的简化版

    2. 定义匿名内部类的前提是,该类必须继承一个外部类或者实现接口。 具体实现如下图 这是一个继承类的正常版,一共分为这几步

    为什么要有内部类

    1. 内部类是为了更好的封装,把内部类封装在外部类里,不允许同包其 他类访问
    2. 内部类中的属性和方法即使是外部类也不能直接访问
    3. 相反内部类可以直接访问外部类的属性和方法,即使private
    4. 利于回调函数的编写。 PS:回调函数是函数的迭代
    5. 当描述事物,如身体里的大脑时,大脑在身体内部,可以通过内部类 直观描述

    内部类特点

    1. 内部类对象不仅指向该内部类,还指向实例化该内部类的外部类对象 的内存。
    2. 内部类和普通类一样可以重写Object类的方法,如toString方法;并 且有构造函数,执行顺序依旧是先初始化属性,再执行构造函数
    3. 在编译完之后,会出现(外部类.class)和(外部类﹩内部类.class) 两个类文件名。
    4. 内部类可以被修饰为private,只能被外部类所访问。事实上一般也都 是如此书写。
    5. 内部类可以被写在外部类的任意位置,如成员位置,方法内。

    内部类对象的建立

    1. 在同包其他类 以及main方法中(前提要内部类没有被修饰成 private,所以一般不采用) 先创建外部类对象,再通过外部类对象创 建内部类
    Out outer = new Out();
    Out.In inner = outer.new In(); //第一个Out是为了说
    明该内部类到底属于哪个外部类
    
    1. 通过匿名外部类创建内部类 Out.In inner = new Out().new In();
    2. 在外部类里 可直接创建对象,如 In inner = new In();或者直接 new In();

    内部类的访问

    1. 静态时,静态内部类只能访问外部类静态成员;非静态内部类都可以直 接访问。(原因是:内部类有一个外部类名.this的指引)当访问外部 类静态成员出现重名时,通过(外部类名.静态成员变量名)访问。如, Out.show();
    2. 重名情况下,非静态时,内部类访问自己内部类通过this.变量名。访 问外部类通过(外部类名.this.变量名)访问 。如Out.this.show();
    3. 在没有重名的情况下,无论静态非静态,内部类直接通过变量名访问 外部成员变量。

    外部类的访问

    1. 内部类为非静态时,外部类访问内部类,必须建立内部类对象。建立 对象方法,如前所述。

    2. 内部类为静态时, 外部类访问非静态成员,通过(外部类对象名.内 部类名.方法名)访问,如new Out().In.function();

    3. 内部类为静态时,外部类访问静态成员时,直接通过(外部类名.内部 类名.方法名) ,如 Out.In.funchtion();

      PS:当内部类中定义了静态成员时,内部类必须是静态的;当外部静态方法访问内部类时,内部类也必须是静态的才能访问

  • 相关阅读:
    sql server 数据定义常用sql
    历史数据处理
    Border不响应MouseDown等点击事件
    wpf 打印A3 & A4 纸张大小的图片
    xml文件读写
    请使用 MakeValid 将该实例转换为有效实例
    接口和抽象类
    索引器&集合
    C#中重写、重载和隐藏的概念
    超图SuperMap iObjects .NET Geometry转geoJSON&WKT&WKB
  • 原文地址:https://www.cnblogs.com/AronJudge/p/14643182.html
Copyright © 2011-2022 走看看