在一个类内部定义的类,叫做内部类。内部类包括:常规内部类,静态内部类,局部内部类,匿名内部类。
A)常规内部类:
常规内部类可以访问外部类所有的变量和方法,内部类中也可以实例化内部类(自己)。
//外部类(外围类)
public class outerClass {
private int age = 20;
//定义内部类
class inner{
//内部类可以定义自己的变量,若变量名与外部类相同,则会覆盖掉外部类的变量
private int ageInner = 10;
public String name = "fxt";
//内部类的方法
public int getAge(){
//内部类可以直接访问外部类的属性和方法,即使是私有的也可以
return age;
}
}
//外部类的方法
public int innerAge(){
return new inner().getAge();
}
public static void main(String[] args) {
//实例化外部类,并访问外部类方法
outerClass ic = new outerClass();
System.out.println(ic.innerAge());
//实例化内部类,并访问内部类方法
outerClass.inner i = ic.new inner();
System.out.println(i.ageInner);
}}
B)静态内部类
使用static修饰内部类,就是静态内部类。静态内部类和静态方法类似,只能访问外部类的静态成员变量和静态方法,而不是像常规内部类那样,直接就可以访问非静态的成员变量和方法。
//外部类(外围类)
public class outerClass {
private int age = 20;
private static int agestatic = 20;
//定义静态内部类
static class inner{
private static int ageinner = 10;
private String name = "fxt";
//内部类的方法
public int getAge(){
//静态内部类不能直接访问外部类非静态的成员变量
// return age; 编译错误
return agestatic;
}
}
public static void main(String[] args) {
//不需要实例化,直接访问静态内部类的静态变量,非静态的访问不了
System.out.println(outerClass.inner.ageinner);
//或者实例化静态内部类,然后访问非静态内容,实例化时直接实例化
outerClass.inner i = new outerClass.inner();
System.out.println(i.name);
}}
C)局部内部类
在方法体或语句块(构造方法、局部块、静态初始化块)等内部定义的类,叫局部内部类。局部内部类不能加任何访问修饰符,例如public、private等,(但是可以加final、abstract),因为它只对局部块有效。
//外部类(外围类)
public class outerClass {
private int age = 20;
//外部类的一个方法
public String getUser(){
//方法中定义的局部内部类
final class user{
String name = "fxt";
public String getName(){
return name;
}
}
return new user().getName();
}
public static void main(String[] args) {
//实例化外部类,并访问外部类的方法
outerClass o = new outerClass();
System.out.println(o.getUser());
}
局部内部类中的属性和方法只能在局部使用,外部无法使用,但是,如果内部类的方法名称定义为可重写(类已存在)的方法名,则可以调用到:
//外部类(外围类)
public class outerClass {
private int age = 20;
//外部类的一个方法
public Object getUser(){
//方法中定义的局部内部类
final class user{
String name = "fxt";
//局部内部类的方法,外部调用不到
public String getName(){
return name;
}
//可重写的内部类方法,外部可以调用
public String toString(){
return name+":toString";
}
}
return new user();
}
public static void main(String[] args) {
//实例化外部类,并访问外部类的方法
outerClass o = new outerClass();
//外部类不能调用内部类的方法,编译错误
// System.out.println(o.getUser().getName());
//外部类可以调用内部类的方法
System.out.println(o.getUser().toString());
}}
D)匿名内部类
匿名内部类可以继承一个类或实现一个接口,但是不需要extends或implements关键字。并且不能同时继承一个类和实现一个接口。
匿名内部类没有名称,所以不能定义构造方法。//外部类(外围类)
public class outerClass {
private int age = 20;
// 返回Contends类,但是Contends接口或类必须存在
public Contents cont() {
//匿名内部类
return new Contents() {
private int i = 11;
public int value() {
return i;
}
//实现的接口的方法
public String name() {
return "fxt";
}
};
}
public static void main(String[] args) {
// 实例化外部类,通过cont()方法返回的类,访问相应的方法
outerClass o = new outerClass();
System.out.println(o.cont().name());
}}
匿名内部类原则:
1、 匿名内部类不能有构造方法。
2、 匿名内部类不能定义任何静态成员、方法和类。
3、 匿名内部类不能是public,protected,private,static。
4、 只能创建匿名内部类的一个实例。
5、 一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类。
6、 因匿名内部类为局部内部类,所以局部内部类的所有限制都对其生效。
内部类的作用:
a) 内部类可以实现隐藏。一般的类不允许有private、protected等访问修饰符,但是内部类可以通过定义为private等,通过访问修饰符定义访问权限。
b) 内部类拥有外围类所有的元素访问权限。
c) 可以间接实现多重继承
当有user和user2两个类时,java不能实现多继承,但是通过内部类,就可以间接实现多继承:
//外部类(外围类)
public class outerClass {
private int age = 20;
//定义内部类,继承user
public class inner1 extends user{
public String getName(){
return super.getName();
}
}
//定义内部类,继承user2
public class inner2 extends user2{
public String getName(){
return super.getName();
}
}
//外部类的方法
public String outerName1(){
return new inner1().getName();
}
//外部类的方法
public String outerName2(){
return new inner2().getName();
}
public static void main(String[] args) {
//实例化外部类,并访问外部类方法
outerClass ic = new outerClass();
System.out.println(ic.outerName1());
System.out.println(ic.outerName2());
}}
d) 可以实现一个类中两个方法名称相同,而不用修改接口。
当需要继承一个类(user),同时实现接口(Contents),这时,例如outerClass2类,若user和Contents中存在方法名称一样的方法,则不能区分是哪一个。(接口中没有实现,默认为继承类中的方法,若outerClass2自己实现了方法,则为自己的方法,但是无法区分这两个方法)。
//外部类继承user
public class outerClass extends user{
//内部类实现接口
class innerClass implements Contents{
public String getName() {
return "ContentsName";
}
}
public static void main(String[] args) {
//实例化外部类,并访问外部类方法
outerClass ic = new outerClass();
System.out.println(ic.getName());
//实例化内部类,并访问内部类方法
outerClass.innerClass oi = ic.new innerClass();
System.out.println(oi.getName());
}}
通过外部类继承,内部类实现接口实现继承类和接口方法名称相同的问题。