详述静态内部类与非静态内部类
将内部类按照是否有static修饰分为静态内部类和非静态内部类,有static修饰的为静态内部类,没有static修饰的为非静态内部类,非静态内部类前面已经讲过,这里不再赘述。
静态有名内部类
public class Body {
/**
* 外部类
*/
public static class Heart{
/**
* 静态有名内部类
*/
public void beat() {
System.out.println("正在跳动......");
}
}
public static void main(String[] args) {
Heart heart = new Heart();
heart.beat();
}
}
import com.jd.Body.Heart;
public class Test {
public static void main(String[] args) {
Heart heart = new Body.Heart();
heart.beat();
}
}
跨类使用静态有名内部类,必须通过new+外部类类名+内部类构造方法调用,在本类中使用则无需通过外部类类名。
静态匿名内部类
class Father {
public void eat() {
System.out.println("筷子吃饭....");
}
}
/**
* 外部类
*/
public class OutClass {
/**
* 匿名内部类
*/
static Father son = new Father(){
@Override
public void eat() {
System.out.println("刀叉吃饭....");
}
};
}
Father类型的变量son,用法相当于静态成员变量
注意:被static修饰的内部类只能直接定义在外部类中
被static修饰的内部类定义在了main方法中,程序报错
静态内部类仅能直接访问外部类的静态成员变量和方法,可以通过创建外部类的对象间接使用非静态的成员变量和方法。
public class OutClass {
private double weight=72;
public static void print(String name) {
System.out.println(name);
}
static class InClass{
{
double weight = new OutClass().weight;//由于weight是非静态的,所以在静态内部类中使用时必须先创建外部类对象
print("Tom");//由于print方法为静态方法,所以可以直接使用。
}
}
public static void main(String[] args) {
InClass inclass = new InClass();
}
}
由于weight变量是非静态的,所以静态内部类中使用时必须先创建对象。print方法是静态的,所以可以直接调用print方法
在非外部类中定义的内部类和局部变量一样,其使用范围从定义的位置开始到其所在直接语句块结束。
public class OutClass {
public static void main(String[] args) {
if(args!=null) {
class InClass{
}
}
InClass inClass = new InClass();//无法创建对象,因为内部类作用范围无法作用到这里
}
}
只有有名静态内部类中才允许有静态成员(静态属性、静态代码块和静态方法)。
原因:静态成员只在类加载时操作一次(静态变量直接赋值,静态方法直接分配地址,静态代码块直接执行),而如果非静态内部类中存在静态成员,则JVM在类加载过静态成员已经操作过一次后,在执行程序时会再次发现非静态代码块中的静态成员,这时,类不会再重新加载,那么这些静态成员将永远不会被执行。
在本类中如何创建内部类对象
public class Mammal {
public void move() {
System.out.println("正在移动......");
}
}
public class Body {
// 1、直接在类中定义的非静态有名内部类
public class Heart{
public void beat() {
System.out.println("正在跳动......");
}
}
public void get() {
Heart heart = new Heart();
heart = this.new Heart();
}
public static void get(String name) {
Heart heart = new Body().new Heart();
}
// 2、直接在类中定义的静态有名内部类
public static class Stomach{
public void work() {
System.out.println("正在蠕动.......");
}
}
public void set() {
Stomach stomach = new Stomach();
// stomach = this.new Stomach();
}
public static void set(String name) {
Stomach stomach = new Stomach();
}
// 3、直接在类中定义的非静态匿名内部类
Mammal mammal = new Mammal() {
@Override
public void move() {
System.out.println("用鱼鳍游动......");
}
};
public void have() {
this.mammal.move();
mammal.move();
}
public static void have(int a) {
new Body().mammal.move();//必须显式创建外部类对象
}
// 4、直接在类中定义的静态匿名内部类
static Mammal whale = new Mammal() {
@Override
public void move() {
System.out.println("用鱼鳍游动......");
}
};
static int a;
public void lost() {
whale.move();
Body.whale.move();
}
public static void lost(int a) {
Body.whale.move();
whale.move();
}
}
直接在类中定义的非静态有名内部类,创建对象时必须先创建外部类对象,在静态代码块方法中创建对象必须显式创建外部类对象。
直接在类中定义的静态有名内部类,创建对象无论是在静态还是非静态代码块或方法中都可以直接创建对象。
直接在类中定义的静态匿名内部类,可以把存有上转型对象的变量当做静态成员变量来使用。