简述:
每个类会产生一个.class文件,文件名即为类名。内部类也会产生这么一个.class文件,但是它的名称却不是内部类的类名,而是有着严格的限制。由外围类的名字,加上$再加上内部类名字。 内部类不是在调用方法时生成,而是与外围类一同编译,就可以通过查看.class文件的方式来证明。
使用内部类的好处:
内部类提供了某种进入外围类的窗户,每个内部类都能独立地继承一个接口,而无论外围类是否已经继承了某个接口。 因此,内部类使多重继承的解决方案变得更加完整。
Inner Class(内部类)
1、定义:一个类的定义放在另一个类的内部,这个类就叫做内部类。
示例:
public class OuterTest {
public class InnerTest {
public void test() {
System.out.println("this is inner Class");
}
}
}
InnerTest就叫做内部类,创建了内部类时,不需任何特殊条件能访问外围类的所有成员。
2、内部类可以访问外围类的任何对象和方法,注意内部类的实现方式与平常的不同
public class OuterTest {
private String str = "hello";
public class InnerTest {
public void test() {
System.out.println(str + " this is inner Class");
}
}
public static void main(String[] args) {
OuterTest ot = new OuterTest();
OuterTest.InnerTest it = ot.new InnerTest();
it.test();
}
}
用外围类创建内部类对象时,此内部类对象会秘密的捕获一个指向外围类的引用,于是,可以通过这个引用来访问外围类的成员。通常,这些都是编译器来处理,我们看不到,也不用关心这个。
3、.this与.new
public class OuterTest {
private int it = 0;
public OuterTest(){
}
public OuterTest(int i){
this.it = i;
}
public class InnerTest {
public void test() {
// 通过.this方法直接获得外围类
System.out.println(OuterTest.this.it);
}
public void test2(OuterTest ot) {
// 传递进来的外围类
System.out.println(ot.it);
}
public void test3() {
System.out.println(new OuterTest().it);
}
}
public static void main(String[] args) {
OuterTest ot = new OuterTest(100);
// 如果想直接创建一个内部类对象,而不是通过外围类对象的方法来得到,可以使用.new关键字
// 必须是外围类对象.new,而不能是外围类.new
OuterTest.InnerTest it = ot.new InnerTest();
it.test();
it.test2(ot);
it.test3();
}
}
.new:想直接创建一个内部类对象,而不是通过外围类对象的方法来得到,可以使用.new关键字,必须是外围类对象.new,而不能是外围类.new
.this:是用来在内部类调用外围类的方法,不需要类对象
而且需要注意的是,在创建外围类对象之前,不可能创建内部类的对象(嵌套类除外:内部静态类)。
4、内部类向接口和父类转换
interface TestIn{
public void printStr();
}
class TestInn {
public void printCls() {
System.out.println("TesTInn");
}
}
public class OuterTest {
private class InnerTest extends TestInn implements TestIn{
public void printStr() {
System.out.println("InnerTest的方法打印");
}
public void printCls() {
System.out.println("InnerTest");
}
}
public TestIn getInner(){
return new InnerTest();
}
public static void main(String[] args) {
OuterTest ot = new OuterTest();
// 通过外围类.new生成
OuterTest.InnerTest it = ot.new InnerTest();
it.printStr();
it.printCls();
// 通过返回接口得到内部类
TestIn it2 = ot.getInner();
it2.printStr();
((TestInn)it2).printCls();
}
}
内部类是private的,除了外围类以外,没人能访问。private内部类给类的设计者提供了一种途径,通过这种方式可以完全阻止任何依赖于类型的编码,并完全隐藏实现的细节。
Anonymous Inner Class 匿名内部类
匿名的内部类是没有名字的内部类。匿名的内部类不能显示地extends(继承)其它类,也不能显示地implements Interface(实现接口)实现。但是能够间接的实现extends(继承)其它类implements Interface(实现接口)。
interface TestIn{
public void printStr();
}
class TestInn {
public void printCls() {
System.out.println("TesTInn");
}
}
public class OuterTest {
public TestIn OuterPrint() {
return new TestIn(){
public void printStr() {
System.out.println("Inner");
}
};
}
public TestInn OuterPrint2() {
return new TestInn(){
public void printCls() {
System.out.println("TesTInn inner");
}
};
}
public static void main(String[] args) {
OuterTest ot = new OuterTest();
ot.OuterPrint().printStr();
ot.OuterPrint2().printCls();
}
}
匿名的内部类传参如果不是final的,编译器就会提示出错,还可以在匿名内部类里定义属性、方法。
class TestInn {
private int num;
public TestInn() {
}
public TestInn(int num) {
this.num = num;
}
public void printCls() {
System.out.println("TesTInn");
}
}
public class OuterTest {
public TestInn OuterPrint(final int num) {
return new TestInn(num){
public void printCls() {
System.out.println("OuterPrint :" + num);
}
};
}
public static void main(String[] args) {
OuterTest ot = new OuterTest();
ot.OuterPrint(200).printCls();
}
}
Nested class(嵌套类/静态的内部类)
static的内部类就叫做嵌套类,嵌套类是个例外,使用嵌套类时有两点需要注意:
1、创建嵌套类对象时,不需要外围类
2、在嵌套类中,不能像普通内部类一样访问外围类的非static成员
class TestInn {
private static int num;
public TestInn() {
}
public TestInn(int num) {
this.num = num;
}
public void printCls() {
System.out.println("TesTInn");
}
public static class TestInner{
public TestInner(int num){
TestInn.num = num;
}
public int getNum(){
return num;
}
};
}
public class OuterTest {
public static void main(String[] args) {
TestInn.TestInner tr = new TestInn.TestInner(200);
System.out.println(tr.getNum());
}
}