今天总结一下Java内部类的使用:首先明确一下定义,所谓内部类就是在一个类的内部定义一个类,根据内部类的定义方式不同,总共分为以下四种:普通内部类(成员内部类),方法内部类,静态内部类和匿名内部类。
1. 成员内部类
首先明确一下成员内部类就是在类的内部直接定义一个类,该类是最普通的一个内部类,顾名思义就是外部类的一个成员。首先看代码如下:
public class Out {
private int age=5;
private int sex=1;
private String str="hello";
private void say(){
System.out.println("我是外部类的say方法");
}
public class Inner {
private int age=20;
private int height=12;
private String str="what";
public void speak(){
int age=30;
System.out.println("我是内部类1的speak方法");
System.out.println("直接访问外部类的不同名变量sex "+sex);//1
System.out.println("直接访问内部类的变量height "+height);//12
System.out.println("直接访问同名变量,是局部变量age:"+age);//30
System.out.println("通过this访问成员内部类的成员变量age:"+this.age);//20
System.out.println("通过外部类.this来访问外部类变量age:"+Out.this.age);//5
}
public void getOut(){
System.out.println(new Out().age+" "+new Out().str);
new Out().say();
}
// public static void haha(){
//
// }
}
private class Inner2 {
private int age=20;
private String str="what2";
public void speak(){
System.out.println("我是内部类2的say方法");
}
}
protected class Inner3 {
private int age=30;
private String str="what3";
public void speak(){
System.out.println("我是内部类3的say方法");
}
}
class Inner4{
// static int a=5;
private int age=40;
private String str="what4";
public void speak(){
System.out.println("我是内部类4的say方法");
}
}
public static void main(String[] args) {
Out out=new Out();
Out.Inner inner=out.new Inner();
System.out.println(inner.age+" "+inner.str);
System.out.println(out.age+" "+out.str);
inner.speak();
inner.getOut();
}
}
输出结果为:
20 what
5 hello
我是内部类1的speak方法
直接访问外部类的不同名变量sex 1
直接访问内部类的变量height 12
直接访问同名变量,是局部变量:30
通过this访问成员内部类的成员变量age:20
通过外部类.this来访问外部类变量age:5
5 hello
我是外部类的say方法
这里看一下Java编译的字节码文件位置在指定目录的bin文件下见下图:
由此可以得出以下结论:
1 . 内部类和外部类经过编译后会生成两个文件,分别是外部类$内部类.class和外部类.class,由于是两个独立的文件,所以内部类允许有和外部类相同的变量名和方法
2 . 一个外部类可以有多个内部类,多个内部类可以 public,protected,private,默认修饰符(friendly)修饰,当然也可以用static修饰。对于外部类只能用public和默认friendly修饰
3 .成员内部类可以访问外部类的所有成员变量和方法,包括私有的属性和方法,在普通内部类中不能有静态变量和方法,因为普通内部类需要依赖外部类来创建,创建格式为 Out.Inner inner=new Outer().new Inner();
4 .如果在内部类的一个普通方法直接访问一个变量,不加任何前缀,分以下几种情况:
4.1如果内外变量同名,那么访问的是内部变量
4.2如果该变量仅存在于内部类,那么访问的就是内部类变量
4.3如果该变量仅存在于外部类,那么可以直接访问,访问的就是外部类变量
4.4如果只想访问内部类变量可以用this.变量名获取,
4.5如果只想访问外部类变量,可以用外部类.this.变量名获取
5 . 普通内部类即成员内部类不能存在静态变量和静态方法。
2 . 局部内部类:
所谓局部内部类就是定义在方法或者作用域内,他的生命周期仅仅存在于方法内部或者作用域内部,具体看下下面代码先:
public class Out {
private int s=100;
private int i=1;
public void say( int k){
//Illegal modifier for the local class Inner; only abstract or final is permitted
int i=5;
final int w=200;
class Inner{
int s=300;
//static int w=20;//不可以定义静态内部类
Inner(int k){
inner(k);
}
int i=200;
void inner(int k){
System.out.println(i);//方法内部类中的i 200
System.out.println(k);//3
System.out.println(s);//方法内部类中的s 300
System.out.println(w);
System.out.println(this.s);//方法内部类中的s 300
System.out.println(Out.this.s);//外部类中的成员变量s 100
}
// public static int haha(){
//
// }
}
new Inner(3);
}
public static void main(String[] args) {
Out out=new Out();
out.say(3);
}
}
200
3
300
200
300
100
public class Out2 {
public void p(final int a, int b){
class Inner{
void print(){
System.out.println(a);
}
}
new Inner().print();
}
public static void main(String[] args) {
new Out2().p(111, 222);
}
}
111
综合以上两段代码可以得出以下结论:
1 . 局部内部类是指定义在方法内部中的类,生命周期与方法的生命周期一致。
2 . 在局部内部类中不能定义静态变量和静态方法(这两种仅限于设置在静态类中)
3 . 如果外部类成员变量和方法内局部变量和内部类中的成员变量一致,那么直接访问变量名访问的是内部类中的成员变量(就近原则).也可以用this.变量名来访问内部类的成员变量
4 . 如果想要访问外部类的成员变量,通过外部类.this.变量名访问。
5 . 如果外部类的方法中的内部类的方法想要访问外部类方法的参数,那么必须用final修饰才可以访问
6 . 方法内部类访问外部类方法中的局部变量,也需要用final修饰
3. 静态内部类:
所谓静态内部类就是在类的内部创建一个用static修饰的类,内部类不依赖于外部类的对象创建而创建,具体看下面代码:
public class Out {
private static int i=1;
private static int k=3;
private int s=10;
public static void f1(){
System.out.println("外部类静态方法");
}
public void f2(){
}
static class Inner{
static int i=2;
int s=20;
static void f4(){
System.out.println("内部类静态方法");
}
static void f3(){
System.out.println(i);//内部类静态变量
System.out.println(k);
// System.out.println(s);不能访问外部类非静态成员和方法
//f2();
f1();
f4();
System.out.println(Out.i);//外部类静态变量
}
}
public static void main(String[] args) {
Out.Inner inner=new Out.Inner();
inner.f3();
}
}
2
3
外部类静态方法
内部类静态方法
1
由上面代码得出以下结论:
1 . 静态内部类的创建不需要外部类对象,格式为外部类.内部类 对象名=new 外部类.内部类(),注意区分它和普通内部类之间的区别。
2 . 静态内部类可以设置静态变量和静态方法,在静态内部类的静态方法可以访问外部类的静态变量和静态方法。如果内部类与外部类变量同名,那么不加修饰符访问的是内部类静态变量名,如果不同名,那么根据变量所在的范围可以具体到外部类还是内部类,如果想访问外部类静态变量,那么可以用外部类.变量名访问。
3 .静态内部类可以直接访问外部类的静态方法,也可以直接访问内部类的静态方法,直接调用即可。
4 .静态内部类不能访问外部类的非静态方法和非静态变量,除非存在外部类对象。
*
4 .匿名内部类
*
匿名内部类就是没有名字的类,由于没有名字,那么只能创建一次,主要作用是用来继承某个类或者是实现接口。我说见过的最常见的使用场景是用来创建多线程使用。
看下面代码,根据两种常见的创建线程的方法,用继承线程类或者是实现runnable接口的类作为Thread的构造方法的参数来实现:
public class Out {
public static void main(String[] args) {
new Thread(){
public void run(){
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()); }
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName());
}
}
}).start();
}
}
匿名内部类的写作格式:new 要继承的类(){
//要重写的从父类继承过来的方法
}或者是
new 接口(){
//实现接口中的声明方法
} //这里表示创建了一个实现了指定接口的内部类
匿名内部类只不过是只使用一次而出现的一种类
结语:
以上大概是Java四种内部类的使用和区别以及注意的地方,想代码举例的时候真是不好想,可能总结了大部分使用情况,后期如果有时间再补充就行了。欢迎指出问题讨论