Java中内部类和静态嵌套类的主要区别是什么?设计/实现是否在选择其中一个方面发挥作用?
当前回答
我认为这里没有什么要补充的,大多数答案完美地解释了静态嵌套类和内部类之间的区别。但是,当使用嵌套类与内部类时,请考虑以下问题。正如在两个答案中提到的,如果没有封闭类的实例,内部类就无法实例化,这意味着它们持有指向封闭类实例的指针,这可能导致内存溢出或堆栈溢出异常,因为即使不再使用封闭类,GC也无法对其进行垃圾收集。要明确这一点,请检查以下代码:
public class Outer {
public class Inner {
}
public Inner inner(){
return new Inner();
}
@Override
protected void finalize() throws Throwable {
// as you know finalize is called by the garbage collector due to destroying an object instance
System.out.println("I am destroyed !");
}
}
public static void main(String arg[]) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
// out instance is no more used and should be garbage collected !!!
// However this will not happen as inner instance is still alive i.e used, not null !
// and outer will be kept in memory until inner is destroyed
outer = null;
//
// inner = null;
//kick out garbage collector
System.gc();
}
如果删除//inner=null;该计划将付诸实施“我被摧毁了!”,但保持评论不会。原因是白色内部实例仍然被引用,GC无法收集它,并且因为它引用(具有指向)外部实例,所以它也没有被收集。项目中有足够的这些对象,可能会耗尽内存。与静态内部类相比,静态内部类不指向内部类实例,因为它与实例无关,而是与类相关。如果将Inner类设置为静态并使用Outer.Inner I=newOuter.Innr()实例化,则上述程序可以打印“我被摧毁了!”;
其他回答
从Java教程:
嵌套类分为两类:静态类和非静态类。声明为静态的嵌套类简单地称为静态嵌套类。非静态嵌套类称为内部类。
使用封闭类名访问静态嵌套类:
OuterClass.StaticNestedClass
例如,要为静态嵌套类创建对象,请使用以下语法:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
作为内部类实例的对象存在于外部类的实例中。考虑以下类别:
class OuterClass {
...
class InnerClass {
...
}
}
InnerClass实例只能存在于OuterClass实例中,并且可以直接访问其封闭实例的方法和字段。
要实例化内部类,必须首先实例化外部类。然后,使用以下语法在外部对象中创建内部对象:
OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
请参见:Java教程-嵌套类
为了完整性,请注意还有这样一种东西,即没有封闭实例的内部类:
class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}
这里,new A(){…}是在静态上下文中定义的内部类,没有封闭实例。
我已经说明了java代码中可能出现的各种可能的正确和错误场景。
class Outter1 {
String OutStr;
Outter1(String str) {
OutStr = str;
}
public void NonStaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// below static attribute not permitted
// static String tempStatic1 = "static";
// below static with final attribute not permitted
// static final String tempStatic1 = "ashish";
// synchronized keyword is not permitted below
class localInnerNonStatic1 {
synchronized public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
public static void StaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// static attribute not permitted below
//static String tempStatic1 = "static";
// static with final attribute not permitted below
// static final String tempStatic1 = "ashish";
class localInnerNonStatic1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
// synchronized keyword is not permitted
static class inner1 {
static String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
public static void innerStaticMethod(String str11) {
// error in below step
str11 = temp1 +" india";
//str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
//}
}
//synchronized keyword is not permitted below
class innerNonStatic1 {
//This is important we have to keep final with static modifier in non
// static innerclass below
static final String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
synchronized public void innerMethod(String str11) {
tempNonStatic = tempNonStatic +" ...";
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// error in below step
public static void innerStaticMethod(String str11) {
// error in below step
// str11 = tempNonStatic +" india";
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
//}
}
}
嵌套类:类内的类
类型:
静态嵌套类非静态嵌套类[内部类]
差异:
非静态嵌套类[内部类]
在非静态嵌套类中,内部类的对象存在于外部类的对象中。因此,内部类可以访问外部类的数据成员。所以要创建内部类的对象,我们必须首先创建外部类的对象。
outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass();
静态嵌套类
在静态嵌套类中,内部类的对象不需要外部类的对象,因为单词“static”表示不需要创建对象。
class outerclass A {
static class nestedclass B {
static int x = 10;
}
}
如果要访问x,请在内部方法中写入以下内容
outerclass.nestedclass.x; i.e. System.out.prinltn( outerclass.nestedclass.x);
这些术语可以互换使用。如果你真的想变得迂腐,那么你可以定义“嵌套类”来引用一个静态的内部类,这个类没有封闭的实例。在代码中,您可能有如下内容:
public class Outer {
public class Inner {}
public static class Nested {}
}
但这并不是一个被广泛接受的定义。
内部类的实例是在创建外部类的实例时创建的。因此,内部类的成员和方法可以访问外部类的实例(对象)的成员和对象。当外部类的实例超出范围时,内部类实例也将停止存在。
静态嵌套类没有具体实例。它只是在第一次使用时加载的(就像静态方法一样)。它是一个完全独立的实体,其方法和变量不能访问外部类的实例。
静态嵌套类不与外部对象耦合,它们速度更快,并且不占用堆/堆栈内存,因为不需要创建此类的实例。因此,经验法则是尽量使用有限的范围(private>=class>=protected>=public)定义静态嵌套类,然后将其转换为内部类(通过删除“static”标识符),如果确实有必要,则放宽范围。
推荐文章
- 找到java类从哪里加载
- 从集合中随机选取一个元素
- 为什么x == (x = y)和(x = y) == x不一样?
- 什么Java 8流。收集等价物可在标准Kotlin库?
- 等待未来的名单
- 如何检查JSON键是否存在?
- 为什么MongoDB Java驱动在条件中使用随机数生成器?
- 即使从未抛出异常,使用try-catch块的代价是否昂贵?
- 什么时候我们应该使用观察者和可观察对象?
- Java中的split()方法对点(.)不起作用。
- Eclipse调试器总是阻塞在ThreadPoolExecutor上,没有任何明显的异常,为什么?
- Java生成两个给定值之间的随机数
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 比较JUnit断言中的数组,简洁的内置方式?
- codestyle;把javadoc放在注释之前还是之后?