**
内部类分为成员内部类,局部内部类,匿名内部类,
bagm:
一、 成员内部类即在成员变量处定义一个内部类,
1、内部类与外部类都可以彼此使用类中的方法,即使是 private 私有的
2、内部类的实例一定要在外部类的实例上,如果从外部类中初始化一个内部类,那么内部类就会绑定在外部类对象上,
3、在主方法中实例一个内部类对象,必须在new操作符前提供一个外部类的引用
并且不能使用外部类的类名,而要用外部内实例的对象来创建
4、非内部不能被声明为private 或 protected访问权限类型,
5、内部类可以实现多继承,以及内部类可以还有内部,(关于这两个用法见 附一内容)
1. package StudyNBNBL;
class Abcd {
AbcdinnerClass abcdinnerClass = new AbcdinnerClass();
private int i = 0;
public class AbcdinnerClass {
// 成员内部类
private int o = 0;
private void print() {
i = 100; // 可以随意使用外部类的私有成员
System.out.println(i);
System.out.println("内部类的abcdinnerClass");
printll(); // 可以随意使用外部类的私有方法
}
}
public void printll() {
System.out.println("外部类的 printll");
}
public void printll2() {
abcdinnerClass.o = 100; // 外部类使用内部类的私用成员
System.out.println(abcdinnerClass.o);
abcdinnerClass.print(); // 调用内部类的方法
}
// 还回一个内部类的引用
public AbcdinnerClass ss() {
return new AbcdinnerClass();
} }
public class StudyNBNBL {
public static void main(String[] args) {
Abcd abcd = new Abcd();
abcd.printll();
abcd.printll2();
Abcd.AbcdinnerClass a = abcd.ss(); // 在类外实例化内部类方法1
Abcd.AbcdinnerClass a2 = abcd.new AbcdinnerClass(); // 在类外实例化内部类方法2
// 在主方法中实例一个内部类对象,必须在new操作符前提供一个外部类的引用 } }
二、使用接口,将一个权限为私有的内部类向上转型为接用,
1、如果将一个内部类权限为private的内部类向上转型为一个父类对象,或是接口时,在程序中将完成隐藏内部类的具体实现过程,
2、内部类的权限为private 所以除了外部类,其它类都不能防问到,
3、但是其它类可以访问到外部类的doit方法,它刚好返回一个内部类引用,
4、接口可以防部到内部类实现了接口的方法,但是方法的具体实现得到了很好的隐藏起来,这就是内部类的基本用法,
5、如果实现了接口的内部类中实现了该接口的方法,就可以定义多个内部类以不同的方式实现接口中的方法同一方法,而一般一个类不能多次实现接口中同一个方法的,
package StudyNBNBL;
interface Out { //定义了一个接口,准备接收私有内部类
public void outprint();
}
class Outclass { // 外部类定义出来
private class Outinclass implements Out { // 内部类定义出来,实现了Out接口
public void outprint() { // 实现了接口,就实现方法
System. out.println("class outinprint -- out outprint");
}
public Outinclass(String s) { //内部类构造方法,显于内部类已经构造完成
System. out.println(s);
}
}
public Outinclass doit() { // 外部类方法,返回一个内部类的引用
return new Outinclass("实例化内部类,访问内部构造方法" );
}
}
public class Test2 {
public static void main(String[] args) { // 在主方法中实现私有内部向上转型为接口
Outclass outclass = new Outclass(); // 先实列外部类对象
Out out = outclass.doit(); // 用接口的引用接用返回的内部类对象
out.outprint(); // 使用接口调用内部实现的方法
}
}
三、使用this处理外部类与内部类变量重名的方法
1、如果遇到外部类与内部类重名,可以用this方法解决,
2、使用就近原则
3、内部中使用this调用内部的变量X,使用类名加this的方法调用外部的变量
4、在内存中所有的对象都放置在堆中,方法以及方法中的形参或局部变量放置在栈中,
package StudyNBNBL;
publicclass Test3 {
private int a = 0; // 定义外部类的 a
private class Test3in {
private int a = 100; // 定义了内部类的a
private void adoit (int a) { // 方法中的形参也为a 是不是乱了
a++; // 就近原则,形参的a加了
this.a ++; // 内部类的a加了
Test3. this.a ++; // 这个用了外部类名加this的当然是外部类的a加了
}
}
}
附一: 内部类可以实现多继承,以及内部类可以还有内部 以及同名变量的调用方法使用
package StudyNBNBL;
class AA { // 定义第一个类
int i = 50;
public void aaprint () {
System. out.println("AA" );
}
}
class BB { // 定义第二个类
int i = 40;
public void bbprint () {
System. out.println("BB" );
}
}
class CC extends AA{ // 定义一个类继承第一个类
int i = 10;
class CCin extends BB{// 定义内部类继承第二个类
int i = 20;
class CCinin {
int i =30;
public void CCininprint (){
System. out.println("CCinin" );
}
public void CCininprint2(){ // 关于内部类多层,以及多继承的同名变量调用
System. out.println(CC.this.i);
System.out.println(CCin.this.i);
System. out.println(i ); // 就近原则
System.out.println(CCin.super.i);
System. out.println(CC.super.i);
}
}
}
}
public class Test6 {
public static void main(String[] args) { // 关于内部多层的申明
CC cc = new CC();
CC.CCin ccin = cc. new CCin();
CC.CCin.CCinin ccinin = ccin. new CCinin();
cc.aaprint();
ccin.bbprint();
ccinin.CCininprint();
CC.CCin.CCinin ccinin2 = new CC().new CCin().new CCinin(); // 一次申明最里面一层内部类的方法
ccinin2.CCininprint2(); // 测试关于内部类多层,以及多继承的同名变量调用
}
}
四、局部内部类
1、即在方法中定义内部类与局部变量类似,方法中的内部类要先定义,后使用,
2、局部内部类不加修饰符,其范围为定义它的代码块
3、局部内部类不能定义静态变量,
4、可以访问外部类的局部变量,但是变量必须是final,(因为局部内部类生命周期的原因,造成访问已经不存在的变量)
5、可以访问外部类的成员变量,
6、变量同名参考this的用法,
7、在类外不能直接生成局部内部类(保证局部类对外不可见的)要想使用局部内部类需外部类对象或接口或使用向上转型,
8、局部类在方法中,该方法以外不能访问局部内部类的成员,
注:局部变量的生命周期与局部内部类对象的生命周期是不一样的,当局部变所处的函数(方法)执行结束后就已经不存在了,可局部内部类还可能一直存在(只要有引用该对象的变量)就会出现访问一个不存在的变量,
package StudyNBNBL;
interface Out2{
public void show();
}
class Abcd2 {
int b = 100;
public Out2 f(final String X) {
final int a = 200;
class AbcdinnerClass implements Out2 { // 不用加权限修饰符,其范围为代码块
AbcdinnerClass(String s) {
s = X; // 只可以方问外部类final的局部变量
System. out.println(s);
}
public void show() {
System. out.println(a + " " + b ); // 可以方问外部类final的局部变量,以外部类的成员变量
System. out.println("Abcinshow" );
}
}
return new AbcdinnerClass( "f -- Abcin" );
}
}
public class Test4 {
public static void main(String[] args) {
Abcd2 abcd2 = new Abcd2();
Out2 out2 =abcd2.f( "no echo");
out2.show();
}
}