Java编程思想之内部类

在这里插入图片描述
内部类 : 可以将一个类的定义放在另一个类的定义内部,内部类允许把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。

/***
 * 内部类的创建 把类定义在外部类里面
 * @author YuSheng_
 *
 */
public class Outer {

	class FisrtInner {
		public void firstMethod() {
			System.out.println("FisrtInner的方法........");
		}
	}

	class SecondInner {
		private String msg;
		SecondInner(String str) {
			msg = str;
		}
		public void secondMethod() {
			System.out.println(msg);
		}
	}
	/***
	 * 外部类中的方法
	 * 这个方法返回一个指向内部类的引用
	 * @param str
	 */
	public void useInnerClass(String str) {
		FisrtInner fisrtInner = new FisrtInner();
		fisrtInner.firstMethod();
		SecondInner secondInner = new SecondInner(str);
		secondInner.secondMethod();
	}

	public static void main(String[] args) {
		Outer outer = new Outer();
		outer.useInnerClass("巅峰迎来虚伪的看客,黄昏见证真正的信徒!");
	}
}

在外部类的非静态方法之外的任意位置创建某个内部类的对象
要具体的指明这个对象的类型 OuterClassName.InnerClassName

public class Outer {

	class FirstInner {
		public void firstMethod(String str) {
			System.out.println("firstMethod执行........" + str);
		}
	}

	class SecondInner {
		public void SecondMethod(String str) {
			System.out.println("SecondMethod执行......." + str);
		}
	}

	public FirstInner getFirstInner() {
		return new FirstInner();
	}

	public SecondInner getSeconInner() {
		return new SecondInner();
	}

	public static void main(String[] args) {
		Outer outer = new Outer();
		FirstInner firstInner = outer.getFirstInner();
		firstInner.firstMethod("海上月是天上月");
		SecondInner seconInner = outer.getSeconInner();
		seconInner.SecondMethod("眼前人是心上人");
		//OuterClassName.InnerClassName
		FirstInner firstInner2 = new Outer().new FirstInner();
		firstInner2.firstMethod("你说啥?");
	}
}

在内部类中可以链接到外部类
意思就是内部类自动拥有对其外部类所有成员的访问权。
当某个外部类的对象创建了一个内部类对象时,此内部类对象必定会秘密捕获一个指向那个外部类对象的引用。
可以看看大手子的文章:

深入理解Java中为什么内部类可以访问外部类的成员 - JAVA编程语言程序开发技术文章 - 红黑联盟
https://www.2cto.com/kf/201402/281879.html

使用.this和.new
如果要生成外部类对象的引用,使用OuterClassName.this。这样产生的引用自动地具有正确的类型

public class OuterClass {

	public void first() {
		System.out.println("调用外部类的方法......");
	}

	class InnerClass {
		public OuterClass getOuterClass() {
			return OuterClass.this;
		}

	}

	public static void main(String[] args) {
		//创建外部类对象并初始化
		OuterClass outerClass = new OuterClass();
		//通过外部类对象获取内部类对象
		InnerClass in = outerClass.new InnerClass();
		//通过内部类对象调用方法 获得外部类对象的引用
		OuterClass outerClass2 = in.getOuterClass();
		//利用外部类对象调用方法
		outerClass2.first();

	}
}

虽然上面的代码看起来是多此一举,但是也说明了.this和.new的用法。
这里要注意的是:
在拥有外部类对象之前是不可能创建内部类对象的,这是因为内部类对象会连接到创建它的外部类对象上。但是,如果是静态内部类,那么久不需要对外部类对象的引用了。.

内部类的向上转型

public class OuterClass02 {
	public static void main(String[] args) {
		Pracel pracel = new Pracel();
		Des des = pracel.getDes();
		des.firstMethod();
		Ant ant = pracel.getAnt();
		ant.secondMethod();
	}
}

interface Des {
	void firstMethod();
}

interface Ant {
	void secondMethod();
}

class Pracel {

	private class DesImpl implements Des {

		public void firstMethod() {
			System.out.println("私有内部类方法调用......");
		}

	}

	protected class AntImpl implements Ant {

		public void secondMethod() {
			System.out.println("保护内部类方法调用......");
		}

	}

	public Des getDes() {
		// 向上转型 Des des = new DesImpl();
		return new DesImpl();
	}

	public Ant getAnt() {
		// 向上转型 Ant ant = new AntImpl();
		return new AntImpl();
	}
}

这种模式指的是 现在Des和Ant这两个接口时客户端程序员可用的接口,因为在Parcel这个类中,两个内部类分别是private和protected的。所以除了Parcel这个类或者二是它的子类都不可以访问这两个内部类。所以如果客户端程序员想访问这些成员,是受到限制的。
另外,这种 private内部类给类的设计者提供了一种途径,通过这种方式,可以完全阻止任何依赖于类型的编码(可能说的是如果不用这种模式,而是使用Parcel去实现那两个接口,就限定了Parcel的类型),并且完全隐藏了所有的细节。
既然这样,我们现在写项目的时候。都是在service层,dao层先写一个接口,然后再进行实现。可不可以仍然写多个接口,然后再一个类的内部建立多个私有内部类,然后私有内部类是接口的实现。感觉是种吃力不讨好的方法。。。但是如果只想把接口给别人用,觉得还凑合啊…

在方法里面或者在任意作用域内定义内部类:

  1. 实现了某类型的接口,可以创建并返回对其的引用
  2. 要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的。
public class OuterClass03 {

	public void method(String str) {

		class Inner {
			private String s;

			Inner(String string) {
				s = string;
			}

			public void InnerMehtod() {
				System.out.println(s);
			}
		}
		Inner inner = new Inner(str);
		inner.InnerMehtod();
	}

	public static void main(String[] args) {
		OuterClass03 class03 = new OuterClass03();
		class03.method("白茶清欢无别事");
	}
}

上面的代码就是将Inner类嵌入到method方法中,可以说为了打印这个问题才创建的Inner类。
同时,Inner类的作用域只限于method方法内部。在此之外,是不可用的。

匿名内部类

public class OuterClass04 {

	public Contents contents() {
		return new Contents() {
			private int i;

			public int value() {
				return 0;
			}
		};
	}

	public static void main(String[] args) {
		OuterClass04 outerClass04 = new OuterClass04();
		Contents content = outerClass04.contents();
		//看看内部类的类型
		System.out.println(content.getClass());
		Contents contents = new Contents();
		System.out.println(contents.getClass());
	}
}

class Contents {

}

打印结果:

class com.YuSheng.thinking.OuterClass04$1
class com.YuSheng.thinking.Contents

上述代码片指的是:创建一个继承自Contents的匿名类的对象,通过new表达式返回的引用被自动向上转型为对Contents的引用。
从上面的打印结果中可以看出,虽然看着像返回了一个Contents类的引用,但是其实并不是这样的。

	public Contents contents(final String str) {
		return new Contents() {
			private String i = str;

			int value() {
				return 0;
			}
		};
	}

要注意的是,如果定义一个匿名内部类,并且希望它使用一个在其外部定义的对象,那么这个参数引用必须是final的。

关于匿名内部类的构造器,因为匿名内部类是没有名字的,所以不可能拥有构造器。但是可以通过实例初始化来达到构造器的效果。

public class OuterClass05 {

	public Luo getLuo(String s) {
		return new Luo(s) {
			{
				System.out.println("实例初始化.....");
			}

			public void f() {
				super.f();
				System.out.println("匿名内部类的f方法别调用........");
			}
		};
	}

	public static void main(String[] args) {
		OuterClass05 outerClass05 = new OuterClass05();
		Luo luo = outerClass05.getLuo("我在等风也等你");
		luo.f();
	}
}

 class Luo {
	Luo(String str) {
		System.out.println(str);
		System.out.println("Luo类的构造器调用.......");
	}

	public void f() {
		System.out.println("Luo类的f方法被调用......");
	}
}

打印结果:

我在等风也等你
Luo类的构造器调用.......
实例初始化.....
Luo类的f方法被调用......
匿名内部类的f方法别调用........

同时 ,这里super.f().的调用也证明了匿名内部类是Luo类的子类。

嵌套类

public class OuterClass06 {

	private String str;

	public void getStr(String s) {
		str = s;
	}
	public static void method02(){
		System.out.println("22");
	}

	static class InnerClass {

		public void method(String str) {
			System.out.println(str);
		}

		public static void method01() {
			System.out.println("内部类静态方法调用....");
		}
	}

	public static void main(String[] args) {
		InnerClass innerClass = new InnerClass();
		//调用普通方法需要内部类对象  但是内部类对象的创建不再依赖于外部类
		innerClass.method("硕鼠硕鼠,无食我黍");
		System.out.println(innerClass.getClass());
		//调用内部类静态方法不需要对象  直接通过类名调用
		InnerClass.method01();
	}
}

打印结果:

硕鼠硕鼠,无食我黍
class com.YuSheng.thiinking.OuterClass06$InnerClass
内部类静态方法调用....

  • 要创建嵌套类的对象,并不需要其外围类的对象
  • 不能从嵌套类的对象中访问非静态的外围类对象

接口中的内部类

书中说道: 正常情况下,不能在接口内部放置任何代码,但嵌套类可以作为接口的一部分。但是放到接口中的任何类都是public和static的。因为类是static的,只是将嵌套类置于接口的命名空间中,这并不违反规则,甚至可以在内部类中实现其对外部类的接口。

public interface OuterClass07 {
	void f();

	class InnerClass {

		public void f01() {
			System.out.println("回眸一笑百魅生,六宫粉黛无颜色");
		}
	}
}
public class Test01 implements OuterClass07{

	public void f() {
		new InnerClass().f01();	
	}
	public static void main(String[] args) {
		new Test01().f();
	}
}

上边的代码并没有在内部类汇中实现对外部类的接口。但是可以刻进行实现,并且重写方法。

关于为什么要使用内部类:

每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口)实现,对于内部类都没有影响。

//内部类具有可以继承多个具体的或者抽象的类的能力

最近有点忙 未完待续…
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值