Java
内部类
分四种:成员 内部类 、局部 内部类 、静态 内部类 和匿名 内部类 。
1、成员 内部类 : 即作为外部类的一个成员存在,与外部类的属性、方法并列。
注意:成员 内部类 中不能定义 静态 变量 ,但可以访问外部类的所有成员。
public class Outer{
private static int i = 1;
private int j=10;
private int k=20;
public static void outer_f1(){
//do more something
}
public void out_f2(){
//do more something
}
//成员 内部类
class Inner{
//static int inner_i =100; // 内部类 中不允许定义 静态 变量
int j=100;// 内部类 中外部类的实例 变量 可以共存
int inner_i=1;
void inner_f1(){
System.out.println(i);//外部类的 变量 如果和 内部类 的 变量 没有同名的,则可以直接用 变量 名访问外部类的 变量
System.out.println(j);//在 内部类 中访问 内部类 自己的 变量 直接用 变量 名
System.out.println(this.j);//也可以在 内部类 中用"this. 变量 名"来访问 内部类 变量
//访问外部类中与 内部类 同名的实例 变量 可用"外部类名.this. 变量 名"。
System.out.println(k);//外部类的 变量 如果和 内部类 的 变量 没有同名的,则可以直接用 变量 名访问外部类的 变量
outer_f1();
outer_f2();
}
}
//外部类的非 静态方法 访问成员 内部类
public void outer_f3(){
Inner inner = new Inner();
inner.inner_f1();
}
//外部类的 静态方法 访问成员 内部类 ,与在外部类外部访问成员 内部类 一样
public static void outer_f4(){
//step1 建立外部 类对象
Outer out = new Outer();
//***step2 根据外部 类对象 建立内部 类对象 ***
Inner inner=out.new Inner();
//step3 访问 内部类 的方法
inner.inner_f1();
}
public static void main(String[] args){
outer_f4();
}
}
成员 内部类 的优点:
⑴ 内部类 作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为PRIVATE,但是对于处于其内部的 内部类 还是可见的。)
⑵ 用 内部类 定义在外部类中不可访问的属性。这样就在外部类 中实 现了比外部类的private还要小的 访问权 限。
注意: 内部类 是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的 内部类 。编译完成后出现outer.class和outer$inner.class两类。
2、局部 内部类 : 即在方法中定义的 内部类 ,与局部 变量 类似,在局部 内部类 前不加修饰符public或private,其范围为定义它的 代码块 。
注意:局部 内部类 中不可定义 静态 变量 ,可以访问外部类的局部 变量 (即方法内的 变量 ),但是 变量 必须是final的。
public class Outer {
private int s = 100;
private int out_i = 1;
public void f(final int k){
final int s = 200;
int i = 1;
final int j = 10;
class Inner{ //定义在方法内部
int s = 300;//可以定义与外部类同名的 变量
//static int m = 20;//不可以定义 静态 变量
Inner(int k){
inner_f(k);
}
int inner_i = 100;
void inner_f(int k){
System.out.println(out_i);//如果 内部类 没有与外部类同名的 变量 ,在 内部类 中可以直接访问外部类的实例 变量
System.out.println(k);//*****可以访问外部类的局部 变量 (即方法内的 变量 ),但是 变量 必须是final的*****
// System.out.println(i);
System.out.println(s);//如果 内部类 中有与外部类同名的 变量 ,直接用 变量 名访问的是 内部类 的 变量
System.out.println(this.s);//用"this. 变量 名" 访问的也是 内部类 变量
System.out.println(Outer.this.s);//用外部"外部类类名.this. 变量 名" 访问的是外部 类 变量
}
}
new Inner(k);
}
public static void main(String[] args) {
//访问局部 内部类 必须先有外部 类对象
Outer out = new Outer();
out.f(3);
}
}
注意:
在类外不可直接生成局部 内部类 (保证局部 内部类 对外是不可见的)。要想使用局部 内部类 时需要生成对象,对象调用方法,在方法中才能调用其局部 内部类 。通过 内部类 和接口达到一个强制的弱 耦合 ,用局部 内部类 来实现接口,并在方法中返回 接口类型 ,使局部 内部类 不可见,屏蔽实现类的 可见性 。
3、静态 内部类 : 静态 内部类 定义在类中,任何方法外,用static定义。
注意:静态 内部类 中可以定义静态或者非静态的成员
public class Outer {
private static int i = 1;
private int j = 10;
public static void outer_f1(){
}
public void outer_f2(){
}
// 静态 内部类 可以用public,protected,private修饰
// 静态 内部类 中可以定义静态或者非静态的成员
static class Inner{
static int inner_i = 100;
int inner_j = 200;
static void inner_f1(){
System.out.println("Outer.i"+i);//静态 内部类 只能访问外部类的 静态成员
outer_f1();//包括 静态 变量 和 静态方法
}
void inner_f2(){
// System.out.println("Outer.i"+j);//静态 内部类 不能访问外部类的非 静态成员
// outer_f2();//包括非 静态 变量 和非 静态方法
}
}
public void outer_f3(){
// 外部类访问 内部类 的 静态成员 : 内部类 . 静态成员
System.out.println(Inner.inner_i);
Inner.inner_f1();
// 外部类访问 内部类 的非 静态成员 :实例化 内部类 即可
Inner inner = new Inner();
inner.inner_f2();
}
public static void main(String[] args) {
new Outer().outer_f3();
}
}
注意:*******生成(new)一个静态 内部类 不需要外部类成员:这是静态 内部类 和成员 内部类 的区别。静态 内部类 的对象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通过生成外部 类对象 来生成。这样实际上使静态 内部类 成为了一个顶级类。静态 内部类 不可用private来进行定义。*******
例子:
对于两个类,拥有相同的方法:
class People
{
run();
}
class Machine{
run();
}
此时有一个robot类:
class Robot extends People implement Machine.
此时run()不可直接实现。
注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用 内部类 来实现。用接口不能完全地实现多 继承 ,用接口配合 内部类 才能实现真正的多 继承 。
4、匿名 内部类
匿名 内部类 是一种特殊的局部 内部类 ,它是通过匿名类实现接口。
IA被定义为接口。
IA I=new IA(){};
匿名 内部类 的特点:
1,一个类用于 继承 其他类或是实现接口,并不需要增加额外的方法,只是对 继承 方法的事先或是覆盖。
2,只是为了获得一个对象实例,不需要知道其实际类型。
3,类名没有意义,也就是不需要使用到。
public class Outer {
private static int i = 1;
private int j = 10;
public static void outer_f1(){
}
public void outer_f2(){
}
// 静态 内部类 可以用public,protected,private修饰
// 静态 内部类 中可以定义静态或者非静态的成员
static class Inner{
static int inner_i = 100;
int inner_j = 200;
static void inner_f1(){
System.out.println("Outer.i"+i);//静态 内部类 只能访问外部类的 静态成员
outer_f1();//包括 静态 变量 和 静态方法
}
void inner_f2(){
// System.out.println("Outer.i"+j);//静态 内部类 不能访问外部类的非 静态成员
// outer_f2();//包括非 静态 变量 和非 静态方法
}
}
public void outer_f3(){
// 外部类访问 内部类 的 静态成员 : 内部类 . 静态成员
System.out.println(Inner.inner_i);
Inner.inner_f1();
// 外部类访问 内部类 的非 静态成员 :实例化 内部类 即可
Inner inner = new Inner();
inner.inner_f2();
}
public static void main(String[] args) {
new Outer().outer_f3();
}
}
注:一个匿名 内部类 一定是在new的后面,用其隐含实现一个接口或实现一个类,没有类名,根据 多态 ,我们使用其父类名。因他是局部 内部类 ,那么局部 内部类 的所有限制都对其生效。匿名 内部类 是唯一一种无 构造方法 类。大部分匿名 内部类 是用于接口回调用的。匿名 内部类 在编译的时候由系统自动 起名 Out$1.class。如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。因匿名 内部类 无 构造方法 ,所以其 使用范围 非常的有限。当需要多个对象时使用局部 内部类 ,因此局部 内部类 的应用相对比较多。匿名 内部类 中不能定义 构造方法 。如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。
________________________________________________________________________________
内部类 总结:
1.首先,把 内部类 作为外部类的一个特殊的成员来看待,因此它有类成员的封闭等级:private ,protected,默认(friendly),public
它有类成员的修饰符: static,final,abstract
2.非静态 内部类 nested inner class, 内部类 隐含有一个外部类的指针this,因此,它可以访问外部类的一切资源(当然包括private)
外部类访问 内部类 的成员,先要取得 内部类 的对象,并且取决于 内部类 成员的封装等级。
非静态 内部类 不能包含任何static成员.
3.静态 内部类 :static inner class,不再包含外部类的 this指针 ,并且在外部类装载时初始化.
静态 内部类 能包含static或非static成员.
静态 内部类 只能访问外部类static成员.
外部类访问静态 内部类 的成员,循一般类 法规 。对于static成员,用类名.成员即可访问,对于非static成员,只能
用对象.成员进行访问
4.对于方法中的 内部类 或块中 内部类 只能访问块中或方法中的final 变量 。
类成员有两种static , non-static,同样 内部类 也有这两种
non-static 内部类 的实例,必须在外部类的方法中创建或通过外部类的实例来创建(OuterClassInstanceName.new innerClassName(ConstructorParameter)),并且可直接访问外部类的信息,外部 类对象 可通过OuterClassName.this来引用
static 内部类 的实例, 直接创建即可,没有对外部类实例的引用。
内部类 不管static还是non-static都有对外部类的引用
non-static 内部类 不允许有static成员
方法中的 内部类 只允许访问方法中的final局部 变量 和方法的final参 数列 表,所以说方法中的 内部类 和 内部类 没什麽区别。但方法中的 内部类 不能在方法以外访问,方法中不可以有static 内部类
匿名 内部类 如果 继承 自接口,必须实现指定接口的方法,且无参数
匿名 内部类 如果 继承 自类,参数必须按父类的 构造函数 的 参数传递
分四种:成员 内部类 、局部 内部类 、静态 内部类 和匿名 内部类 。
1、成员 内部类 : 即作为外部类的一个成员存在,与外部类的属性、方法并列。
注意:成员 内部类 中不能定义 静态 变量 ,但可以访问外部类的所有成员。
public class Outer{
private static int i = 1;
private int j=10;
private int k=20;
public static void outer_f1(){
//do more something
}
public void out_f2(){
//do more something
}
//成员 内部类
class Inner{
//static int inner_i =100; // 内部类 中不允许定义 静态 变量
int j=100;// 内部类 中外部类的实例 变量 可以共存
int inner_i=1;
void inner_f1(){
System.out.println(i);//外部类的 变量 如果和 内部类 的 变量 没有同名的,则可以直接用 变量 名访问外部类的 变量
System.out.println(j);//在 内部类 中访问 内部类 自己的 变量 直接用 变量 名
System.out.println(this.j);//也可以在 内部类 中用"this. 变量 名"来访问 内部类 变量
//访问外部类中与 内部类 同名的实例 变量 可用"外部类名.this. 变量 名"。
System.out.println(k);//外部类的 变量 如果和 内部类 的 变量 没有同名的,则可以直接用 变量 名访问外部类的 变量
outer_f1();
outer_f2();
}
}
//外部类的非 静态方法 访问成员 内部类
public void outer_f3(){
Inner inner = new Inner();
inner.inner_f1();
}
//外部类的 静态方法 访问成员 内部类 ,与在外部类外部访问成员 内部类 一样
public static void outer_f4(){
//step1 建立外部 类对象
Outer out = new Outer();
//***step2 根据外部 类对象 建立内部 类对象 ***
Inner inner=out.new Inner();
//step3 访问 内部类 的方法
inner.inner_f1();
}
public static void main(String[] args){
outer_f4();
}
}
成员 内部类 的优点:
⑴ 内部类 作为外部类的成员,可以访问外部类的私有成员或属性。(即使将外部类声明为PRIVATE,但是对于处于其内部的 内部类 还是可见的。)
⑵ 用 内部类 定义在外部类中不可访问的属性。这样就在外部类 中实 现了比外部类的private还要小的 访问权 限。
注意: 内部类 是一个编译时的概念,一旦编译成功,就会成为完全不同的两类。对于一个名为outer的外部类和其内部定义的名为inner的 内部类 。编译完成后出现outer.class和outer$inner.class两类。
2、局部 内部类 : 即在方法中定义的 内部类 ,与局部 变量 类似,在局部 内部类 前不加修饰符public或private,其范围为定义它的 代码块 。
注意:局部 内部类 中不可定义 静态 变量 ,可以访问外部类的局部 变量 (即方法内的 变量 ),但是 变量 必须是final的。
public class Outer {
private int s = 100;
private int out_i = 1;
public void f(final int k){
final int s = 200;
int i = 1;
final int j = 10;
class Inner{ //定义在方法内部
int s = 300;//可以定义与外部类同名的 变量
//static int m = 20;//不可以定义 静态 变量
Inner(int k){
inner_f(k);
}
int inner_i = 100;
void inner_f(int k){
System.out.println(out_i);//如果 内部类 没有与外部类同名的 变量 ,在 内部类 中可以直接访问外部类的实例 变量
System.out.println(k);//*****可以访问外部类的局部 变量 (即方法内的 变量 ),但是 变量 必须是final的*****
// System.out.println(i);
System.out.println(s);//如果 内部类 中有与外部类同名的 变量 ,直接用 变量 名访问的是 内部类 的 变量
System.out.println(this.s);//用"this. 变量 名" 访问的也是 内部类 变量
System.out.println(Outer.this.s);//用外部"外部类类名.this. 变量 名" 访问的是外部 类 变量
}
}
new Inner(k);
}
public static void main(String[] args) {
//访问局部 内部类 必须先有外部 类对象
Outer out = new Outer();
out.f(3);
}
}
注意:
在类外不可直接生成局部 内部类 (保证局部 内部类 对外是不可见的)。要想使用局部 内部类 时需要生成对象,对象调用方法,在方法中才能调用其局部 内部类 。通过 内部类 和接口达到一个强制的弱 耦合 ,用局部 内部类 来实现接口,并在方法中返回 接口类型 ,使局部 内部类 不可见,屏蔽实现类的 可见性 。
3、静态 内部类 : 静态 内部类 定义在类中,任何方法外,用static定义。
注意:静态 内部类 中可以定义静态或者非静态的成员
public class Outer {
private static int i = 1;
private int j = 10;
public static void outer_f1(){
}
public void outer_f2(){
}
// 静态 内部类 可以用public,protected,private修饰
// 静态 内部类 中可以定义静态或者非静态的成员
static class Inner{
static int inner_i = 100;
int inner_j = 200;
static void inner_f1(){
System.out.println("Outer.i"+i);//静态 内部类 只能访问外部类的 静态成员
outer_f1();//包括 静态 变量 和 静态方法
}
void inner_f2(){
// System.out.println("Outer.i"+j);//静态 内部类 不能访问外部类的非 静态成员
// outer_f2();//包括非 静态 变量 和非 静态方法
}
}
public void outer_f3(){
// 外部类访问 内部类 的 静态成员 : 内部类 . 静态成员
System.out.println(Inner.inner_i);
Inner.inner_f1();
// 外部类访问 内部类 的非 静态成员 :实例化 内部类 即可
Inner inner = new Inner();
inner.inner_f2();
}
public static void main(String[] args) {
new Outer().outer_f3();
}
}
注意:*******生成(new)一个静态 内部类 不需要外部类成员:这是静态 内部类 和成员 内部类 的区别。静态 内部类 的对象可以直接生成:
Outer.Inner in=new Outer.Inner();
而不需要通过生成外部 类对象 来生成。这样实际上使静态 内部类 成为了一个顶级类。静态 内部类 不可用private来进行定义。*******
例子:
对于两个类,拥有相同的方法:
class People
{
run();
}
class Machine{
run();
}
此时有一个robot类:
class Robot extends People implement Machine.
此时run()不可直接实现。
注意:当类与接口(或者是接口与接口)发生方法命名冲突的时候,此时必须使用 内部类 来实现。用接口不能完全地实现多 继承 ,用接口配合 内部类 才能实现真正的多 继承 。
4、匿名 内部类
匿名 内部类 是一种特殊的局部 内部类 ,它是通过匿名类实现接口。
IA被定义为接口。
IA I=new IA(){};
匿名 内部类 的特点:
1,一个类用于 继承 其他类或是实现接口,并不需要增加额外的方法,只是对 继承 方法的事先或是覆盖。
2,只是为了获得一个对象实例,不需要知道其实际类型。
3,类名没有意义,也就是不需要使用到。
public class Outer {
private static int i = 1;
private int j = 10;
public static void outer_f1(){
}
public void outer_f2(){
}
// 静态 内部类 可以用public,protected,private修饰
// 静态 内部类 中可以定义静态或者非静态的成员
static class Inner{
static int inner_i = 100;
int inner_j = 200;
static void inner_f1(){
System.out.println("Outer.i"+i);//静态 内部类 只能访问外部类的 静态成员
outer_f1();//包括 静态 变量 和 静态方法
}
void inner_f2(){
// System.out.println("Outer.i"+j);//静态 内部类 不能访问外部类的非 静态成员
// outer_f2();//包括非 静态 变量 和非 静态方法
}
}
public void outer_f3(){
// 外部类访问 内部类 的 静态成员 : 内部类 . 静态成员
System.out.println(Inner.inner_i);
Inner.inner_f1();
// 外部类访问 内部类 的非 静态成员 :实例化 内部类 即可
Inner inner = new Inner();
inner.inner_f2();
}
public static void main(String[] args) {
new Outer().outer_f3();
}
}
注:一个匿名 内部类 一定是在new的后面,用其隐含实现一个接口或实现一个类,没有类名,根据 多态 ,我们使用其父类名。因他是局部 内部类 ,那么局部 内部类 的所有限制都对其生效。匿名 内部类 是唯一一种无 构造方法 类。大部分匿名 内部类 是用于接口回调用的。匿名 内部类 在编译的时候由系统自动 起名 Out$1.class。如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。因匿名 内部类 无 构造方法 ,所以其 使用范围 非常的有限。当需要多个对象时使用局部 内部类 ,因此局部 内部类 的应用相对比较多。匿名 内部类 中不能定义 构造方法 。如果一个对象编译时的类型是接口,那么其运行的类型为实现这个接口的类。
________________________________________________________________________________
内部类 总结:
1.首先,把 内部类 作为外部类的一个特殊的成员来看待,因此它有类成员的封闭等级:private ,protected,默认(friendly),public
它有类成员的修饰符: static,final,abstract
2.非静态 内部类 nested inner class, 内部类 隐含有一个外部类的指针this,因此,它可以访问外部类的一切资源(当然包括private)
外部类访问 内部类 的成员,先要取得 内部类 的对象,并且取决于 内部类 成员的封装等级。
非静态 内部类 不能包含任何static成员.
3.静态 内部类 :static inner class,不再包含外部类的 this指针 ,并且在外部类装载时初始化.
静态 内部类 能包含static或非static成员.
静态 内部类 只能访问外部类static成员.
外部类访问静态 内部类 的成员,循一般类 法规 。对于static成员,用类名.成员即可访问,对于非static成员,只能
用对象.成员进行访问
4.对于方法中的 内部类 或块中 内部类 只能访问块中或方法中的final 变量 。
类成员有两种static , non-static,同样 内部类 也有这两种
non-static 内部类 的实例,必须在外部类的方法中创建或通过外部类的实例来创建(OuterClassInstanceName.new innerClassName(ConstructorParameter)),并且可直接访问外部类的信息,外部 类对象 可通过OuterClassName.this来引用
static 内部类 的实例, 直接创建即可,没有对外部类实例的引用。
内部类 不管static还是non-static都有对外部类的引用
non-static 内部类 不允许有static成员
方法中的 内部类 只允许访问方法中的final局部 变量 和方法的final参 数列 表,所以说方法中的 内部类 和 内部类 没什麽区别。但方法中的 内部类 不能在方法以外访问,方法中不可以有static 内部类
匿名 内部类 如果 继承 自接口,必须实现指定接口的方法,且无参数
匿名 内部类 如果 继承 自类,参数必须按父类的 构造函数 的 参数传递