1、什么是内部类
定义:将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)。
2、内部类的访问规则
(1)
内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用。
格式:外部类名
.this
(2)
外部类要访问内部类,必须建立内部类对象。
3、内部类的访问格式
(1)
当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中直接建立内部类对象。
格式:
外部类名
.
内部类名 变量名
=
外部类对象
.
内部类对象
;
Outer.Inner in = new Outer().new Inner();
(2)
当内部类定义在局部位置上,也可以直接访问外部类中的成员。
同时可以访问所在局部中的局部变量,但必须是被
final 关键字
修饰的。
(3)
当内部类在成员位置上,就可以被成员修饰符所修饰。
比如:
private
:将内部类在外部类中进行封装。
static
:内部类就具备静态的特性。
内部类代码示例:
class InnerClassDemo {
public static void main(String[] args){
Outer.Inner in = new Outer().new Inner(); //创建一个内部类对象
in.show(); //调用内部类对象中的show()方法
}
}
class Outer {
int x = 3;
class Inner {
int x = 4;
void show() {
System.out.println("show:"+Outer.this.x);
}
}
}
结果:
以上示例也可以写成这样:
class InnerClassDemo {
public static void main(String[] args){
new Outer().function(); //new一个父类的匿名对象
}
}
class Outer {
int x = 3;
class Inner {
int x = 4;
void show() {
System.out.println("show:"+Outer.this.x);
}
}
public void function() {
new Inner().show(); //new一个子类的匿名对象
}
}
运行结果一样。
定义在函数中的内部类(局部位置的内部类):
class InnerClassDemo {
public static void main(String[] args){
new Outer().run(6); //new一个匿名对象
}
}
class Outer {
int x = 3;
public void run(final int a){
final int y = 5; //内部类若想访问局部变量,此变量必须被 final修饰,a和y均被final修饰
class Inner {
int z = 4;
void show() {
System.out.println("show y:"+y+" show a:"+a); //可直接访问局部变量 a和y
}
}
new Inner().show(); //new一个匿名对象
}
}
运行结果:
4、静态内部类
当内部类被
static
修饰后,只能直接访问外部类中的
static
成员。出现访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
new Outer.Inner().show();
在外部其他类中,如何直接访问static内部类的静态成员呢?
Outer.Inner.show();
注意:当内部类中定义了静态成员,该内部类必须是static的。
直接访问static内部类的非静态成员:
class InnerClassDemo {
public static void main(String[] args){
new Outer.Inner().show(); //访问内部类的非静态成员.show()方法为非静态
}
}
class Outer {
static int x = 3;
static class Inner {
static int y = 4;
void show() {
System.out.println("show x:"+Outer.x+" show y:"+Inner.y);
}
}
}
结果:
直接访问static内部类的静态成员:
class InnerClassDemo {
public static void main(String[] args){
Outer.Inner.show(); //访问内部类的静态成员,全为静态;
}
}
class Outer {
static int x = 3;
static class Inner {
static int y = 4;
static void show() {
System.out.println("show x:"+Outer.x+" show y:"+Inner.y);
}
}
}
结果:
5、内部类定义原则
a) 当描述事物时,事物的内部还有事物,该事物用内部类来描述。
b) 因为内部事物在使用外部事物的内容。
6、匿名对象
匿名对象:new的一个对象直接调用其方法,而不给此对象命名
如: new Outer().function();
为,直接创建了一个Outer类型的对象,并直接调用此对象的function()方法。此过程中没有给此对象命名。
7、匿名内部类
a) 匿名内部类就是内部类的简写格式。
b) 定义匿名内部类的前提:内部类必须是继承一个类或实现一个接口。
c) 匿名内部类的格式:new 父类或接口(){定义子类的内容};
d) 其实匿名内部类就是一个匿名子类对象,而这个对象有点胖,可以理解为带内容的对象。
e) 匿名内部类中,定义的方法最好不要超过3个。
匿名内部类代码示例:
class InnerClassDemo {
public static void main(String[] args){
new Outer().function(); //new一个匿名对象
}
}
abstract class AbsDemo{
abstract void show();
}
class Outer {
int x = 3;
public void function(){
new AbsDemo(){ //匿名内部类,是AbsDemo类的子类对象
void show(){ //重写父类AbsDemo中的抽象方法
System.out.println("x = :"+x);
}
void abc(){ //子类中建立一个子类方法abc()
System.out.println("abc");
}
}.show(); //直接调用子类对象的show()函数
}
}
结果:
父类引用指向匿名内部类,匿名内部类其实是个子类(多态情形)
class InnerClassDemo {
public static void main(String[] args){
new Outer().function(); //new一个匿名对象
}
}
abstract class AbsDemo{
abstract void show();
}
class Outer {
int x = 3;
public void function(){
AbsDemo b = new AbsDemo(){ //多态,父类引用指向子类对象
void show(){ //重写父类AbsDemo中的抽象方法
System.out.println("x = :"+x);
}
void abc(){ //子类中建立一个子类方法abc()
System.out.println("abc");
}
};
b.show();
//b.abc(); 多态错误,父类中没有abc()方法,编译时出错
}
}