zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Java 内部类分析

JAVA 分析 内部
2023-09-14 09:10:16 时间

一、简介

        因为现在是Android开发实习生。发现在发展过程中越来越多,但他们知道什么时候该使用真实的情况,但没有获得,例如,使用内部类,因此,学习和自己的总结后发现,通过互联网的信息,家分享,如有不当之处。万望指出。

二、内部类

内部类是指在一个外部类的内部再定义一个类,是一个编译时的概念。一旦编译成功,内部类与其外部类就会成为全然不同的两类,仅仅是内部类的前面会冠以外部类的类名和$符号,如一个outer类内部定义了一个inner的内部类,那么编译完毕后会生成outer.class和outer$inner.class两个类,因此内部类的成员变量与方法能够与外部类同样。
从内部类的定义上来看。事实上内部类严重破坏了良好的代码结构。那么为什么还要使用内部类呢?由于内部类能够任意使用外部类的成员变量(包含私有的)而不用生成外部类对象,这也是内部类的唯一长处。

三、内部类的分类及演示样例

        内部类分为成员内部类、局部内部类、静态内部类和匿名内部类。以下针对各个内部类进行介绍:

    (1)成员内部类

 

        作为外部类的一个成员存在,与外部类的属性、方法并列。成员内部类中能够訪问外部类的全部成员,当外部类的变量与内部类的变量名反复时,使用外部类名.this.变量名能够对外部类的变量进行调用。假设没有反复时可直接使用变量名进行调用。在普通外部类方法中訪问静态内部类可new出成员内部类对象进而直接调用当中的方法,而在静态外部类方法中须要先new出外部类对象,再调用外部类对象名.new 内部类的方式来获得成员内部类对象。

        成员内部类中不能定义静态变量,由于成员内部类须要先创建了外部类,才干创建它自己的。


        成员内部类能够使用外部类的私有成员和属性。同一时候其在外部类中定义了不可訪问的属性,这样就在外部类中实现了比外部类的private还要小的訪问权限。

演示样例代码例如以下:

/**
 * 
 * @ClassName: MemberInnerClass
 * @Description: 成员内部类
 * @author ADAM
 * @date 2014年7月25日 上午9:20:28
 *
 */
public class MemberInnerClass {
	private int i = 0;

	public class Inner {// 成员内部类可加权限修饰符
		int i = 3;

		public void print() {
			System.out.println(i);// 输出为内部类的i。值为3
			System.out.println(this.i);// 输出为内部类的i,值为3
			System.out.println(MemberInnerClass.this.i);// 输出外部类的i,值为0
		}
	}

	public void print() {
		(new Inner()).print();// 外部类普通方法调用成员内部类直接new出内部类进行调用
	}

	public static void main(String[] args) {
		((new MemberInnerClass()).new Inner()).print();// 外部类静态方法中调用成员内部类首先new出外部类然后new出内部类进行调用
	}
}

    (2)局部内部类

        即在方法中定义的内部类,与局部变量类似。在局部内部类前不加修饰符public或private。其范围为定义它的代码块。

局部内部类中不可定义静态变量。能够訪问外部类(即方法)中的变量。可是变量必须是final。局部内部类与外部类的命名重名时的调用方法与成员内部类同样,訪问局部内部类必须得先有外部类对象。

        在类外不可直接生成局部内部类(保证局部内部类对外是不可见的)。要想使用局部内部类时须要生成外部类对象,对象再去调用方法,在方法中才干调用其局部内部内。

通过内部类与接口达到了一个强制的弱耦合,用局部内部类来实现接口。并在方法中返回接口类型,使局部内部类不可见。屏蔽实现类的可见性。

演示样例代码例如以下:

/**
 * 
 * @ClassName: LocalInnerClass 
 * @Description: 局部内部类
 * @author ADAM
 * @date 2014年7月25日 上午10:36:26 
 *
 */
public class LocalInnerClass {
	private int j = 3;
	private int i = 2;

	public void test() {
		MemberInnerClass memberInnerClass = new MemberInnerClass();
// 若要訪问其它类中的成员内部类仅仅能当该成员内部类的修饰符为public才可
// 否则编译错误,即成员内部类能够再类内部实现比private还要小的权限
		memberInnerClass.new Inner();
		final int i = 0;
		class Inner {// 此处不得加上private等修饰符,否则编译错误
			int i = 1;

			public void print() {
				System.out.println(j);饰符。否则编译错误
				System.out.println(i);// 此时输出局部内部类的i,外部方法中的变量仅仅能通过传參的形式进行调用
				System.out.println(LocalInnerClass.this.i);// 此时输出的是外部类中的i
			}
		}
		Inner inner = new Inner();// 局部内部类仅仅能在方法内实例化并进行调用
		inner.print();
	}

	public static void main(String[] args) {
		(new LocalInnerClass()).test();
	}
}

         局部内部类不仅能够定义在方法中还能够定义在作用域内。下面提供两个Thinking in Java的样例

定义在方法内:

public class Parcel4 { 
    public Destination destination(String s) { 
        class PDestination implements Destination { 
            private String label; 
 
            private PDestination(String whereTo) { 
                label = whereTo; 
            } 
 
            public String readLabel() { 
                return label; 
            } 
        } 
        return new PDestination(s); 
    } 
 
    public static void main(String[] args) { 
        Parcel4 p = new Parcel4(); 
        Destination d = p.destination("Tasmania"); 
    } 
} <span style="line-height: 1.3em; font-family: 'Courier New', monospace; background-color: inherit;"> </span>

定义在作用域里:

public class Parcel5 { 
    private void internalTracking(boolean b) { 
        if (b) { 
            class TrackingSlip { 
                private String id; 
                TrackingSlip(String s) { 
                    id = s; 
                } 
                String getSlip() { 
                    return id; 
                } 
            } 
            TrackingSlip ts = new TrackingSlip("slip"); 
            String s = ts.getSlip(); 
        } 
    } 
 
    public void track() { 
        internalTracking(true); 
    } 
 
    public static void main(String[] args) { 
        Parcel5 p = new Parcel5(); 
        p.track(); 
    } 
} 

         局部内部类也像别的类一样进行编译,仅仅是作用域有所不同。仅仅在该方法或者条件的作用域内才干使用。出了这些作用域则无法被使用。

    (3)静态内部类

         静态内部类也称为嵌套内部类,定义在类中,不论什么方法外。用static定义,静态内部类中能够定义静态或非静态的成员,其可用public、private等修饰符修饰,一般使用public修饰。方便调用,其仅仅能訪问外部类中的静态成员。外部类訪问静态内部类中的静态成员时直接使用内部类.静态成员,訪问静态内部类的非静态成员时先实例化静态内部类再通过对象訪问。

         生成一个静态内部类不须要外部类对象成员。这是与成员内部类的差别,同一时候普通内部类不能有static方法和属性,也不能包括嵌套类,静态内部类的对象能够直接生成:外部类.内部类 对象名= new 外部类.内部类()就可以

         注意:当类与接口(或者接口与接口)发生方法命名冲突时,必须使用内部类来实现。

用接口不能全然地实现多继承,用接口配合内部类才干实现真正的多继承。

演示样例代码例如以下:

/**
 * 
 * @ClassName: StaticInnerClass 
 * @Description: 静态内部类
 * @author ADAM
 * @date 2014年7月25日 上午10:37:04 
 *
 */
public class StaticInnerClass {
	private int i = 1;
	public static int j = 1;
	public int k = 0;

	public static class Inner {
		private int i = 0;
		private static int j = 0;// 可定义静态与非静态成员

		public static void print() {
//			System.out.println(k);// 编译错误,不得调用外部类中的非静态成员
			System.out.println(new StaticInnerClass().i);//訪问外部类中的非静态成员变量须要先实例化外部类
			System.out.println(j);
			System.out.println(new StaticInnerClass().j);// 静态内部类使用外部类中的静态成员
		}
	}

	public static void main(String[] args) {
		Inner.print();// 外部类静态方法或者非静态方法调用静态内部类中的静态成员时直接内部类名.成员就可以
		StaticInnerClass.Inner inner = new StaticInnerClass.Inner();// 静态内部类的实例化不须要先实例化外部类
		System.out.println(inner.i);// 訪问静态内部类中的非静态成员时须要先实例化静态内部类
	}
}

通过内部类实现多继承演示样例代码例如以下:

/**
 * 
 * @ClassName: Pencil 
 * @Description: 笔类
 * @author ADAM
 * @date 2014年7月25日 上午10:42:59 
 *
 */
public abstract class Pencil {
	public abstract void write();
}
/**
 * 
 * @ClassName: Eraser 
 * @Description: 橡皮擦类
 * @author ADAM
 * @date 2014年7月25日 上午10:43:28 
 *
 */
public abstract class Eraser {
	public abstract void erase();
}
/**
 * 
 * @ClassName: PencilWithEraser 
 * @Description: 多继承类
 * @author ADAM
 * @date 2014年7月25日 上午10:43:53 
 *
 */
public class PencilWithEraser {
	private MyPencil pencil = new MyPencil();
	private MyEraser eraser = new MyEraser();

	private class MyPencil extends Pencil {//继承笔类

		@Override
		public void write() {
			System.out.println("To Write");
		}

	}

	private class MyEraser extends Eraser {//继承橡皮擦类
		@Override
		public void erase() {
			System.out.println("To Erase");
		}

	}

	// 本类自己的方法。调用继承类中的方法
	public void write() {
		pencil.write();
	}

	public void erase() {
		eraser.erase();
	}

	public static void main(String[] args) {
		PencilWithEraser pencilWithEraser = new PencilWithEraser();
		pencilWithEraser.write();
		pencilWithEraser.erase();
	}
}

    (4)匿名内部类

         用于继承其它类或是实现接口,并不须要添加额外的方法,仅仅是对继承方法的重写或实现,也使用于仅仅是为了得到一个对象实例,不须要知道事实上际类型,此时类名是没有意义的,也不须要被使用到。
演示样例代码例如以下:

/**
 * 
 * @ClassName: AnonymousInnerClass 
 * @Description: 匿名内部类
 * @author ADAM
 * @date 2014年7月25日 上午10:38:25 
 *
 */
public class AnonymousInnerClass {
	public void click(OnClickListener onClickListener) {
		System.out.println("click,click");
	}

	public static void main(String[] args) {
		AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
		anonymousInnerClass.click(new OnClickListener() {// 直接new出匿名内部类,不须要保存对象。一般用于继承其它类或是实现接口
					@Override
					public void onClick() {
						System.out.println("Inner Click");
					}
				});
	}
}

四、总结

         因为眼下还是处于学习阶段,对于内部类的使用最多的也是成员内部类和匿名内部类。所以对于诸如非常仔细地去区分各个内部类的使用场景以及涉及到的更小的訪问权限的作用等方面体会并非非常深刻,之后有更进一步的学习会补上,也希望看到这篇博文的朋友假设有一些其它的见解或者补充或者是推荐学习的资料也能够提出来,这篇博文也是借鉴网上各位大神以及百科的相关资料,再自己手动编码验证总结果出,感恩节你大神,谢谢。



版权声明:本文博客原创文章。博客,未经同意,不得转载。