内部类都可以继承父类和实现多个接口(不过一般不提倡实现多层的内部类)
1.匿名内部类:
匿名:没有名字,即这里说的是类没有名字
内部类:
在另一个类中声明的类,称为内部类。
匿名对象:对象没名字
1、匿名内部类的语法格式
我们声明一个类的目的,是为了创建对象,然后通过对象调用方法什么的。
那么这里这个类都没有名字,那么怎么创建对象。
(1)因为是匿名内部类,那么必须在声明类的同时创建对象。现在不创建,后面没法创建了。
(2)因为是匿名内部类,那么只能借助它父类或父接口的名字。
语法格式:
A:调用父类的无参构造器
new 父类(){
写类的成员
}
B:调用父类的有参构造
new 父类(实参列表){
写类的成员
}
C:用Object的无参构造,因为接口没有构造器
new 父接口(){
写类的成员
}
class Father{
public void method(){
System.out.println("父类的方法");
}
}
public static void main(String[] args) {
//是Father的子类对象,这个类没有名字
// 同时它还创建了一个该子类的对象。
Father f = new Father(){
public void method(){
System.out.println("子类的方法");
}
};
}
还可以作为实参传递,形成多态
2.静态内部类:
2、特点
(1)静态内部类它也是一个类
它的字节码文件名:外部类名$静态内部类名.class(2)静态内部类也可以有自己的成员:没有限制
所有类的成员在静态内部类中都可以声明。
(3)静态内部类是否可以使用外部类的成员,包括私有的(可以)、静态的(有限制)?
有限制。静态内部类不能使用外部类的非静态成员。
(4)在外部类中使用静态内部类是否有限制?没有限制
说明:如果你要使用静态内部类的静态方法等,那么直接使用"静态内部类名."即可
如果你要使用静态内部类的非静态方法等,那么直接使用"静态内部类对象."即可
(5)在外部类的外面 使用静态内部类是否有限制?没有限制
说明:如果你要使用静态内部类的静态方法等,那么直接使用"静态内部类名."即可
如果你要使用静态内部类的非静态方法等,那么直接使用"静态内部类对象."即可
只不过在外面使用时,要注意静态内部类的全名称是“包名.外部类名.静态内部类名",可以使用import语句简化使用(6)在外部类可以使用静态内部类的私有属性
public class TestStaticInner {
public static void main(String[] args) {
//调用Inner类中的test()方法
Inner in = new Inner();
in.test();
//调用Inner类中的method()方法
Inner.method();
/* //调用Inner类中的test()方法
Outer.Inner in = new Outer.Inner();
in.test();
//调用Inner类中的method()方法
Outer.Inner.method();*/
}
}
class Outer{
private static int a = 1;
private int b = 2;
public static class Inner{
public void test(){
System.out.println(a);
// System.out.println(b);//错误的
}
public static void method(){
System.out.println(a);
// System.out.println(b);//错误的
}
}
public void outTest(){
//调用Inner类中的test()方法
Inner in = new Inner();
in.test();
//调用Inner类中的method()方法
Inner.method();
}
public static void outMethod(){
//调用Inner类中的test()方法
Inner in = new Inner();
in.test();
//调用Inner类中的method()方法
Inner.method();
}
}
3.非静态内部类
2、特点
(1) 非静态内部类也是类,也有自己的字节码文件
外部类名$非静态内部类名.class
(2) 非静态内部类中声明成员,是否有限制
有限制:不能有静态的成员
(3)非静态内部类中使用外部类的成员是否有限制
没有限制
(4)在外部类中使用非静态内部类是否有限制
有限制
静态方法等成员中不能使用非静态内部类
(5)在外部类的外面使用非静态内部类
可以使用,只不过需要外部类的对象,才能使用非静态内部类(6)在外部类中可以使用内非静态内部类的私有属性
public class TestNonStaticInner {
public static void main(String[] args) {
//使用Outer的outMethod()
Outer out = new Outer();
out.outMethod();
//使用Inner的method
//即要使用非静态内部类需要外部类的对象
//Outer.Inner in = out.new Inner();
// Outer.Inner in = out.getInner();//换一种方法
Inner in = out.getInner();
in.method();
}
}
class Outer{
private static int a;
private int b;
class Inner{
public void method(){
System.out.println(a);
System.out.println(b);
}
}
public void outMethod(){
//使用Inner的method
Inner in = new Inner();
in.method();
}
public static void outTest(){
//使用Inner的method
// Inner in = new Inner();//错误的,因为outTest方法是静态的,不能使用非静态的Inner
// in.method();
}
//返回非静态内部类的对象
public Inner getInner(){
return new Inner();
}
}
4.局部内部类
2、特点
(1)局部内部类也是类,也是有字节码文件
外部类名$编号局部内部类名.class
(2)局部内部类中声明类的成员,是否有限制
不能有静态成员
总结:除了静态内部类中可以有静态成员,其他的内部类中统统都不能声明静态成员。
(3)在局部内部类中使用外部类的成员,是否有限制
有限制,但是限制和局部内部类无关,看所在的方法,所在的方法是静态的,就不能使用非静态的
(4)在外部类中,使用局部内部类是否有限制?
局部内部类有作用域
(5)在外部类的外面使用局部内部类?不能
(6)在外部类的外面是否可以获取局部内部类的对象?可以,但是只能用父类或父接口的变量接收这个对象
(7)在局部内部类中可以使用外部类的作用域范围内的局部变量,但是这个局部变量必须是final的。
JDK1.8之前,必须手动加final,JDK1.8之后默认自动加final
为什么?
如果没有final,那么就是普通的局部变量,是在栈中存储,那么方法调用结束后,就内存自动释放了,
而我们方法中的局部内部类的对象可能被返回到外面使用,如果通过这个对象调用方法,又要使用这个局部变量,
就无法访问了。所以要用final修饰,使得它称为常量,值存储到方法区的常量池中。
强调:匿名内部类也是局部内部类的一种,只是没有名字。
public class TestLocalInner {
public static void main(String[] args) {
Outer out = new Outer();
Object obj = out.test4();
System.out.println(obj.getClass());//获取对象的运行时类型
// obj.method();//obj编译时类型是Object类型,无法向下转型为Inner了
MyInter my = out.test5();
my.method();
}
}
class Outer{
private static int a;
private int b;
public void test1(){
// Inner in = new Inner();//错误的
class Inner{
public void method(){
System.out.println(a);
System.out.println(b);
}
}
Inner in = new Inner();
in.method();
}
public static void test2(){
class Inner{
public void method(){
System.out.println(a);
// System.out.println(b);//错误的,test2是静态的,不能使用b
}
}
}
public void test3(){
//调用Inner的method方法
// Inner in = new Inner();//错误,无法使用,因为上面的Inner都是局部的,都有作用域
// in.method();
}
public Object test4(){
class Inner{
public void method(){
System.out.println(".....");
}
}
Inner in = new Inner();
return in;
}
public MyInter test5(){
final int num = 10;//外部类Outer的test5方法的局部变量
class Inner implements MyInter{
@Override
public void method() {
System.out.println("num = " + num);
}
}
return new Inner();
}
}
interface MyInter{
void method();
}