如何从(静态)类中创建一个新的类实例?

8

我是Java的新手(有C#的经验),

这是我的需求:

public final class MyClass
{
    public class MyRelatedClass
    {
      ...
    }
}

public class OtherRandomClass
{
    public void DoStuff()
    {
       MyRelatedClass data = new MyClass.MyRelatedClass(); 
    }
}

在Eclipse中会出现以下错误:

无法访问BitmapEffects的任何封闭实例。必须使用BitmapEffects的封闭实例来限定分配(x.new A(),其中x是BitmapEffects的一个实例)。

C#中可以使用静态类完成此操作,那么在这里应该如何实现呢?


可能是重复的问题:Java - No enclosing instance of type Foo is accessible - fabian
4个回答

19

根据您定义的MyRelatedClass类,您需要有一个MyClass实例才能访问/实例化该类。

通常在Java中,当MyRelatedClass的一个实例需要访问MyClass实例的某些字段时,您会使用这种模式(因此编译器警告中出现了对“封闭实例”的引用)。

下面的代码应该可以编译:

public void doStuff() {
   MyClass mc = new MyClass();
   MyRelatedClass data = mc.new MyRelatedClass(); 
}

然而,如果一个MyRelatedClass实例不需要访问其封闭实例(MyClass的字段),那么您应该考虑将MyRelatedClass定义为静态类,这样可以使您发布的原始代码编译通过。

嵌套类(您所发布的内容)和静态嵌套类(一个class中的static class)之间的区别在于,前者是属于父类实例的,而后者则没有这种关系,只有逻辑/命名空间关系。


4
在除了隐式this以外的任何对象上创建一个(非静态)内部类会让我感到不适。 - Tom Hawtin - tackline
我正在尝试在Java中实现C#中的功能://[MapManagement.cs] namespace MapManagement { public static class MapManager { ... }public class SpecialMapFile { ... }}我想要在一个文件中有两个类(非静态),但在Java中这是不允许的...错误:“公共类型名称需要在自己的文件中定义”,所以这是我的解决方案,我想要一个包,并且我希望将相关的类分组放在它们自己的文件中。 - Mervin
@Mervin,正如你所见,Java只允许每个文件有一个公共顶级类。相关的类可以在同一个包中定义,在不同的文件中。 - matt b

4

我不想让MyRelatedClass成为静态的,我需要多个实例。 - Mervin
1
@Mervin,请阅读链接中的描述(或马特的回答)。如果内部类是“静态”的,这并不意味着它只有一个实例。它意味着MyRelatedClass不会与MyClass的任何特定实例相关联,也不能访问其(父类)实例成员。 - Nikita Rybak
@Mervin - 在这个上下文中,static的意思并不是那样。它实际上使得它的行为就像一个顶级类一样,尽管它是嵌套在MyClass中的。 - Robin
我正在尝试在Java中实现我在C#中可以做到的事情: //[MapManagement.cs] namespace MapManagement { public static class MapManager { ... } public class SpecialMapFile { ... } } 我想要在一个文件中有两个类(非静态),但在Java中这是不允许的...错误:“公共类型名称需要在自己的文件中定义”,所以这是我的解决方案,我想要一个包,并且我希望将相关的类分组放在它们自己的文件中。 - Mervin
Java非常希望您每个文件只有一个公共类。强烈建议您坚持这一点,而不是试图绕过它。 - Steven Schlansker

2
关于在一个文件中打包多个类的评论,Java的大多数实现与.NET不同,强制要求公共类类型的名称与声明该类类型的文件的名称之间存在严格的对应关系。这不是硬性要求,但未使用强制执行此对应关系的系统。JLS - 7.6 Top Level Type Declarations 表示:

当包存储在文件系统中时(§7.2.1),主机系统可能会选择强制执行以下限制:如果满足以下任一条件,则在类型未在以类型名称加扩展名(例如.java或.jav)组成的名称下找到文件时,会导致编译时错误:

  • 该类型由所在包的其他编译单元中的代码引用。
  • 该类型被声明为public(因此可能从其他包中的代码访问)。
查看这个SO问题:一个文件中的多个类声明 如果你想创建一个命名空间来封装你相关的类,那么使用静态内部类就是你需要的。静态声明并不意味着只有一个实例 - 它们仍然可以被实例化 - 静态意味着它们可以在不需要对封闭类进行引用的情况下被实例化。由于封闭类只是用于分组而不是数据,所以将其设置为静态是安全的。为了更清楚地表明封闭类只是用于分组,你应该将其声明为一个接口,这样它就不能被实例化并且没有实现细节。
虽然个人认为,我会避免这样做 - 在Java中,包被用来强制执行命名空间。使用内部类很快变得繁琐。(我已经尝试过了!)

0

是的,非静态嵌套类可以访问外部类的实例成员,因此必须为外部类的一个实例创建它。所以你有两个选择:

  1. 像Mervin建议的那样将嵌套类设为静态的,或者
  2. 按照错误消息建议的使用外部类的实例来创建它。

在实践中,我很少创建内部类的实例,除了在外部类的方法中,而且我很少使这样的类可变--但这只是我的做法。


我正在尝试在Java中实现我在C#中可以做到的事情: //[MapManagement.cs] namespace MapManagement { public static class MapManager { ... } public class SpecialMapFile { ... } } 我想要在一个文件中有两个类(非静态),但在Java中这是不允许的...错误提示:"公共类型名称需要在自己的文件中定义",所以这是我的解决方案,我想要一个包,并且我希望将相关的类分组放在它们自己的文件中。 - Mervin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接