内部类
内部类:在一个类的内部在定义一个新的类。
内部类的分类:
- 成员内部类
- 静态内部类
- 方法内部类
- 匿名内部类
一个简单的内部类
public class Outer{
class Inner{
}
}
根据它的概念恒容易理解,接下来我们来看一下内部类的不同形式
成员内部类
class Out {
int a = 1; // 外部类属性
Inner i = new Inner(); //创建内部类对象
private void fun(){
i.print1(); //调用内部类方法
System.out.println(i.num);
}
class Inner{
int num = 2;
private void print1(){
// fun(); 内部类调用外部类方法和属性
System.out.println(a);
}
}
}
通过以上代码我们可以很直观的看到在内部类与外部类中可以互相访问他们的私有属性和方法
public class OuterTest{
public static void main(String[] args) {
//在外部类以外的其他类中实例内部类对象
Out.Inner o = new Out().new Inner();
Out p = new Out();
p.fun();
o.print1();
}
}
在OuterTest中我们可以通过外部类.内部类 对象名 = new 外部类().内部类() 的方式去实例化一个对象,则可以通过这样的方式去调用内部类与外部的成员和方法。
成员内部类中的注意事项:
1.内部类在外部使用时,无法直接实例化,需要借助由外部信息才能完成实例化操作
2.内部类的访问权限修饰符任意,但是访问范围会受到影响,同时注意在内部类中不可以定义static的属性与方法
3.内部类可以直接访问外部类的成员属性,如果由同名属性,默认会调用内部类的属性
4.可以通过 外部类.this.同名变量 的形式访问外部类的同名属性
5.内部类编译后的储存命名格式是:外部类$内部类.class
6.内部类中包含外部类同名方法时,若在内部类中使用外部类同名方法格式: 外部类.this.同名方法
方法内部类
顾名思义定义在方法中的内部类,同样的因为它定义在了这个方法体中,那么它的作用域就只有方法中了
class Out{
public Object method(){
class methodInner{
// static int weight; 在方法内部类中同样不可以写静态的属性与方法
int age = 10;
public String name(){
return "张三";
}
}
return new methodInner().name();
}
}
public class OuterTest{
public static void main(String[] args) {
Out o = new Out();
//获取方法内部类实例
System.out.println(o.method());
}
}
注意事项
1.方法内部类不能写静态成员
2.方法内部类使用:一般情况下返回方法内部类中的方法
静态内部类
静态内部类就是被static修饰的内部类
class Out{
static int j = 777;
int b = 888;
static class Inner2{
//定义一个静态属性
static String sex;
//创建静态内部类对象
static Out o1 = new Out();
public void print0(){
//如果要访问外部类的非静态成员,需要用外部类对象的实例
System.out.println(o1.b);
o1.fun();
}
}
}
public class OuterTest{
public static void main(String[] args) {
// Out o = new Out();
// System.out.println(o.method());
//获取静态内部类实例
Out.Inner2 inner2 = new Out.Inner2();
inner2.sex = "man";
inner2.print0();
//调用外部类静态属性
System.out.println(Out.j);
//调用外部类非静态属性
System.out.println(new Out().b);
}
}
注意事项
1.静态内部类中,可以直接访问外部类的静态成员。如果要访问外部类的非静态成员,需要用外部类对象的实例
2.静态内部类对象实例时,可以不依赖外部类的实例
3.可以通过外部类.内部类.静态方法的形式调用静态内部类的静态成员
4.当内部类属性与外部类属性同名时,内部类默认调用的是内部类的成员属性
如果需要访问外部类的静态属性,可以通过外部类.属性名的方式获取
如果需要访问外部类的非静态属性,通过new 外部类().属性的方式获取
匿名内部类
没有名字的内部类, 在使用时只使用一次
匿名内部类一般是接口或抽象类的实现类或子类
package inner;
abstract class Device{
private String name;
public abstract double getPrice();
public String getName(){
return name;
}
public Device(String name){
this.name = name;
}
}
class Annoy{
public void test(Device device){
System.out.println("购买一个" + device.getName()+"花费了" + device.getPrice());
}
}
public class OuterTest{
public static void main(String[] args) {
Annoy annoy = new Annoy();
annoy.test(new Device("格力空调") {
@Override
public double getPrice() {
return 3000.0;
}
});
}
}
注意事项:
1.匿名内部类没有类型名称、实例对象的名称
2.匿名内部类编译后的储存名称是:外部类$数字.class
3.匿名内部类没有构造方法,但是可以有构造代码块初始化
4.不能有private、protected、abstract、static、final关键字修饰
5.匿名内部类中不能有静态成员
6.匿名内部类可以实现接口也可以继承父类,但是不可兼得