内部类 : 可以将一个类的定义放在另一个类的定义内部,内部类允许把一些逻辑相关的类组织在一起,并控制位于内部的类的可视性。
/***
* 内部类的创建 把类定义在外部类里面
* @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层先写一个接口,然后再进行实现。可不可以仍然写多个接口,然后再一个类的内部建立多个私有内部类,然后私有内部类是接口的实现。感觉是种吃力不讨好的方法。。。但是如果只想把接口给别人用,觉得还凑合啊…
在方法里面或者在任意作用域内定义内部类:
- 实现了某类型的接口,可以创建并返回对其的引用
- 要解决一个复杂的问题,想创建一个类来辅助你的解决方案,但是又不希望这个类是公共可用的。
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();
}
}
上边的代码并没有在内部类汇中实现对外部类的接口。但是可以刻进行实现,并且重写方法。
关于为什么要使用内部类:
每个内部类都能独立的继承自一个(接口的)实现,所以无论外围类是否已经继承了某个(接口)实现,对于内部类都没有影响。
//内部类具有可以继承多个具体的或者抽象的类的能力
最近有点忙 未完待续…