嵌套类分两类:带static关键字的静态嵌套类和不带static关键字的非静态嵌套类,第二种不带static关键字的非静态嵌套类也就是我们常说的内部类。
一、带static关键字的静态嵌套类(Static Nested Class)
静态嵌套类只可以访问外部类里的静态变量和静态方法,不可以访问非静态变量和非静态方法。
class OuterClass {
static int static_number = 0;
static void method1() {
}
static class StaticNestedClass {
int a = 9;
void test() {
method1();
System.out.println(static_number + " " + a);
}
}
}
public class InnerTest1 {
public static void main(String[] args) {
OuterClass.StaticNestedClass innerObject =new OuterClass.StaticNestedClass();
innerObject.test();
}
}
二、非静态嵌套类或者内部类(Non-static Nested Class 或者 Inner Class)
因为内部类是与外部类的实例相关联的,所以内部类里不可以有静态变量和静态方法,同时 内部类可以访问外部类里的所有变量和方法,不论是静态的还是非静态的。
class OuterClass {
static int static_number = 0;
int number = 1;
static void method1() {
}
void method2() {
}
class NestedClass {
//static int static_number2 = 0;//编译错误
static final int AGE = 2;
int number2;
void test(){
method2();
method1();
System.out.println(static_number + " " + number);
}
}
}
public class InnerTest1 {
public static void main(String[] args) {
OuterClass outerObject = new OuterClass();
//内部类是与外部类的实例相关联的,
//所以创建内部类实例前必须先创建外部类实例
//也正是因为这种关联,使得内部类里不可以有静态的变量与方法,常量除外(static final)
<pre name="code" class="java"> OuterClass.NestedClass innerObject = outerObject.new NestedClass();
innerObject.test();}}
三:内部类的两种特别情况:本地内部类和匿名内部类( local classes and anonymous classes)
本地内部类--通常将这种类写在方法内部,作为内部类的一种,本地内部类不可以有静态变量和静态方法,
public class LocalClassExample {
static String regularExpression = "regularExpression";
int index = 0;
public static void validatePhoneNumber(final String phoneNumber1) {//因为这个参数被本地内部类使用,所以必须为final,JDK8以后不用必须声明final
final int numberLength = 10;//因为这个变量被本地内部类使用,所以必须为final,JDK8以后不用必须声明final
class PhoneNumber {//因为这个内部类位于静态方法内部,所以不可以访问外问类里的实例变量,即非静态变量
String formattedPhoneNumber = null;
//static int number = 1;
PhoneNumber(String phoneNumber){
formattedPhoneNumber = phoneNumber;
}
public void print() {
System.out.println(numberLength + " " + formattedPhoneNumber);
System.out.println(regularExpression);
//编译错误
//System.out.println(index);
}
}
PhoneNumber myNumber1 = new PhoneNumber(phoneNumber1);
myNumber1.print();
}
public void validatePhoneNumber2(final String phoneNumber1) {//因为这个参数被本地内部类使用,所以必须为final,JDK8以后不用必须声明final
final int numberLength = 10;//因为这个变量被本地内部类使用,所以必须为final,JDK8以后不用必须声明final
class PhoneNumber2 {//因为这个内部类位于非静态方法内部,所以可以访问外问类里的实例变量,即非静态变量
String formattedPhoneNumber = null;
//static int number = 1;
PhoneNumber2(String phoneNumber){
formattedPhoneNumber = phoneNumber;
}
public void print() {
System.out.println(numberLength + " " + formattedPhoneNumber);
System.out.println(regularExpression);
System.out.println(index);
}
}
PhoneNumber2 myNumber2 = new PhoneNumber2(phoneNumber1);
myNumber2.print();
}
public static void main(String[] args) {
validatePhoneNumber("123-456-7890");
LocalClassExample example = new LocalClassExample();
example.validatePhoneNumber2("123-456-7890");
}
}
匿名内部类--它是一个表达式
public class HelloWorldAnonymousClasses {
interface HelloWorld {
public void greet();
}
public void sayHello() {
HelloWorld spanishGreeting = new HelloWorld() {
public void greet() {
System.out.println("hello");
}
};
spanishGreeting.greet();
}
public static void main(String[] args) {
HelloWorldAnonymousClasses myApp =new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
匿名内部类可以访问它所在的外部类的方法和变量,当然,如果匿名内部类处于外部类的静态方法里时,则它只能访问外部类 的静态变量和方法。
当匿名内部类位于方法里面时,如果它要使用方法参数或者方法里的本地变量,则这些参数和变量必须声明成final类型(JDK1.8以后有所变化),匿名内部类作为内部类的一种,在类的内部自然也不可以有静态变量和静态方法。
四:同名变量
如果要访问内部类和外部类的同名变量时,请参照以下示例
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);//FirstLevel.x
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);//ShadowTest.x
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}