内部类:可以包含在另外一个类中的类
外部类:包含内部类的类
每个内部类都会被编译为一个独立的类,生成一个独立的字节码文件。
内部类可以方便地访问外部类的私有变量,内部类也可以声明为private从而实现对外完全隐藏。
java中的四种内部类(根据定义的位置和方式划分)
-静态内部类
-成员内部类
-方法内部类
-匿名内部类
特征:在类的内部中存在另一个类,且该类被static修饰
使用范围:在外部类内,可以直接使用内部类,在外部类范围以外使员外部类名.静态内部类名的方式使用内部类
public class StaticOuter {
private static int shared = 100;
public static class StaticInner{
public void staticInnerMethod() {
System.out.println("Static Inner Method" + shared);
}
}
StaticInner si1 = new StaticInner();
public void test() {
StaticInner si = new StaticInner();
si.staticInnerMethod();
}
public static void main(String[] args) {
StaticOuter so = new StaticOuter();
so.test();
//在外部类范围内
StaticInner si1 = new StaticInner();
si1.staticInnerMethod();
//合法
StaticOuter.StaticInner si2 = new StaticOuter.StaticInner();
si2.staticInnerMethod();
}
}
//在外部类范围外
class Test{
StaticOuter.StaticInner si2 = new StaticOuter.StaticInner();
}
访问范围
静态内部类只能访问外部类中的static变量和方法。
静态内部类也可以访问外部类中的private变量。
静态内部类中可以定义静态变量和静态方法。
语法:成员内部类作为外部类的一个成员存在
使用方法:
如何新建一个内部类的实例:不能直接使用外部类.内部类的方式,每个成员内部类对象对应一个外部类实例,因此需要先创建一个外部类实例,然后才能生成内部类的实例(如下面代码)
访问范围:
成员内部类可以访问外部类中的静态变量和方法,也可以访问实例变量和方法。但是书写格式有两种:
(1)直接访问;
(2)外部类.this.xxx,主要针对外部类和内部类的出现变量重名或者方法重名的情况。
成员内部类也可以访问外部类的私有变量
成员内部类中不可以定义静态变量和静态方法(final变量例外,它等同于常量),在后面的方法内部类和匿名内部类中也是不能存在静态的变量和方法的,这是因为静态变量和静态方法作为类型的属性和方法,一般是独立使用的,而成员内部类和一个对一个的外部类实例关联,一般不会独立使用,所以这样的使用意义不大。(这算是一种规定吧)。
public class OriginalClass {
private static int t1 = 100;
private int t2 = 200;
class OriginalInner{
public void test() {
/*
* 不合法的表示,在成员内部类中不可以定义静态的变量和方法
public static int inner = 100;
public static void print() {
}
*/
//合法的final变量
public static final int inner1 = 300;
System.out.println("OriginalInner:"+ t1);//直接访问外部类静态变量
System.out.println("OriginalInner:"+ t2);//直接访问外部类成员变量
action();//直接访问外部类方法
System.out.println("OriginalInner:"+ OriginalClass.this.t1);//
System.out.println("OriginalInner:"+ OriginalClass.this.t2);
OriginalClass.this.action();
}
}
public void action() {
System.out.println("originalinner action");
}
public static void main(String[] args) {
//new一个内部类
OriginalClass oc = new OriginalClass();
OriginalInner oi = oc.new OriginalInner();
oi.test();
}
}
语法:存在于方法体内部的类
使用范围:方法内部类只能在定义的方法内被使用
访问范围:
如果包含内部类的方法是实例方法,那么可以访问外部类的静态变量和方法,也可以访问实例变量和方法;
如果包含内部类的方法是静态方法,那么只能访问外部类的静态变量和方法。
方法内部类还可以直接访问方法的参数和方法中的局部变量,但是这些变量必须声明为final。为什么需要声明为final呢?这是因为方法内部类操作的并不是外部的变量,而是它自己的实例变量,只是这些变量的值和外部一样,对这些变量赋值,并不会改变外部的值,为避免混淆,所以干脆强制规定必须声明为final。
我们知道被final修饰的基本类型变量的值是不能被修改的,被final修饰的数组或者引用类型变量的引用是不能修改的,即只能指向一个对象或者是数组,但是我们可以修改对象中的成员变量值或者是数组中元素的值。
其实使用final来修饰参数以及局部变量的目的还是保证方法内部类外面的元素不会在方法内部类中被修改,相当于限制一个作用域的功能,保证方法内部类内部的的修改不会影响方法内部类外面的同名变量值。
public class FunctionOuter {
private static int s= 100;
private int s1 = 20;
public void print(final int param) {
final int in = 300;
class FunctionInner{
public void innertest() {
System.out.println("FunctionInner:s="+s);
System.out.println("FunctionInner:s1="+s1);
System.out.println("FunctionInner:in"+ in);
test();
}
}
FunctionInner fi = new FunctionInner();
fi.innertest();
System.out.println("print:in"+in);
}
public void test() {
System.out.println("FunctionOuter:"+s);
}
public static void main(String[] args) {
FunctionOuter fo = new FunctionOuter();
fo.print(900);
}
}
语法:匿名内部类没有单独的类定义,它在创建对象的同时定义类
new 父类(参数列表){
//匿名内部类实现部分
}
new 父接口(){
//匿名内部类实现部分
}
匿名内部类只能使用一次,用来创建一个对象。没有名字,没有构造方法,但是可以根据参数列表,调用对应的父类构造方法。
在匿名内部类中可以定义实例变量和方法,以及初始化代码块,初始化代码块可以起到构造方法的作用,只是构造方法可以有多个,但是初始化代码块只能有一块,因为没有构造方法,它自己无法接受参数,如果必须要参数,则应该是用其他内部类。
匿名内部类可以访问外部类的所有变量和方法,可以访问方法中的final参数和局部变量