Java中有类似内部类的东西吗?

Posted

技术标签:

【中文标题】Java中有类似内部类的东西吗?【英文标题】:Is there anything like an Internal class in Java? 【发布时间】:2011-08-24 06:40:54 【问题描述】:

在 C# 中,您可以将类标记为 internal,以便只能从同一个包中访问它。 Java中有类似的东西吗?

【问题讨论】:

***.com/questions/2534733/java-protected-classes的可能重复 @cmmi:并不是真正的重复,因为这个问题是从完全不同的角度提出的。虽然答案相同。 请注意,C# 没有packages——它们有namespacesassemblies。包相当于命名空间。但是可以将程序集与 Java 中的 JAR 文件进行比较。 internal 修饰符使类只能在程序集中访问。因此,它与命名空间或包无关。 【参考方案1】:

您可以通过在类的声明中省略安全修饰符(public、private)来创建包私有类。

package com.sample;

class MyPackagePrivateClass

    ...

【讨论】:

封装比汇编更好 @hB0 :不可能!您将如何声明在不同包中引用的“内部”帮助程序类?你根本不能 我的意思是“一种更好的软件设计方式”,而不是更多的功能密集型(MS 总是附带) 虽然我同意包是一个远离命名空间的定义,但是当类必须相互调用时,对类库的几个部分进行编程可能会有些奇怪,但你不希望它们成为可以从该库外部访问,然后如果您想实现这一点,则不能将这些类放在单独的包中。可能创建一个“内部”包,对于仅由自己的库使用的类可能是最安全的出路。 Jar 可见修饰符不是 Java 的一部分,因为 jar 是打包的。可以手动将已经编译的类压缩在一起(我不得不在各种情况下这样做) - 如果在 java 中“内部”是可能的,那将允许人们轻松访问类之间不应该具有这种可见性的“内部”方法。 . jar 不像 dll 那样以严格的方式封装。【参考方案2】:

删除访问修饰符与 C# 中的 internal 类似。

C#

public class A

    public static int X;
    internal static int Y;
    private static int Z;

internal class B

    public static int X;
    internal static int Y;
    private static int Z;
    public class C
    
        public static int X;
        internal static int Y;
        private static int Z;
    
    private class D
    
        public static int X;
        internal static int Y;
        private static int Z;
    

Java

public class A

    public static int X;
    static int Y;
    private static int Z;

class B

    public static int X;
    static int Y;
    private static int Z;
    public class C
    
        public static int X;
        static int Y;
        private static int Z;
    
    private class D
    
        public static int X;
        static int Y;
        private static int Z;
    

来源:http://www.javacamp.org/javavscsharp/internal.html

【讨论】:

仅当 A、B、C、D 类在同一个包中时才有效。在 C# 中,它们只需要在同一个命名空间中, @User1234 在同一个程序集中,而不是命名空间。【参考方案3】:

这个问题之前有一个公认的答案,但我认为对于来自 .Net 的 Java 新手来说,答案并不完全清楚。

java 在 C# 中是否有一些与 internal 修饰符完全相同的等价物?简短的回答是否定的(但你可以通过一些方法实现它,我会告诉你)!!

internal 在 C# 中实际上是一个“程序集私有”修饰符。什么是程序集?

Assembly 是您项目的任何产品(C# 中的 DLL 或 EXE - java 中的等价物可以是 JAR 文件)

在 java 中没有任何与 internal 完全等价的东西。 Bryan Kyle 回答并接受的实际上是“包私有”(java 中的包等同于 C# 中的命名空间),但有些回答是获得相同结果的最接近的方法。

但是如何获得与 internal 完全相同的结果? java不能解决这个问题吗?答案是肯定的。

确实有。但不带修饰符。 实际上,做到这一点的最佳方法是包装中的秘密。打包的最佳做法是按类的关系而不是类型打包您的类。

我们中的许多人使用名为“Models”或“Presenters”的包并将我们所有的模型或演示者放入其中。虽然这是错误的。包应该像“Book”,包含“BookModel.java”、“BookPresenter.java”、.....

这样,您可以通过省略修饰符使它们成为包私有,并且没有任何问题,因为您可以在任何需要您的包私有类的类中访问它们,因为您有良好的打包实践。

【讨论】:

【参考方案4】:

是的。它被称为包私有,你只需定义没有任何修饰符的类:

package com.blah; class Foo

【讨论】:

【参考方案5】:

我不熟悉 C#,但在 Java 中,默认保护是某些内容只能在包内访问:

public=任何人都可以访问

private=只能在当前类中访问

protected=可在包内或从当前类继承的任何类中访问

default=在包内可访问

我一直认为应该有一种方法可以说“任何继承自当前类但不能从其他任何地方、这个包或任何其他地方继承的类都可以访问”。但是没有。

【讨论】:

对于您的最后一条评论,C# 具有“受保护的内部” @projectshave 没有错。 C# 中的“受保护的内部”也可以从整个程序集中访问。实际上,将一个类的访问权限限制在 C# 中的子类中,请使用“受保护”。而在 java 中,“受保护”将可以从同一个包以及子类中访问。【参考方案6】:

您可以将类包本地化。这是类的默认范围。即你没有访问修饰符。

如果你真的想放一些时间,你可以创建一个注释,例如@package_local,我在我特别希望它是本地包的地方执行此操作,而不仅仅是未指定它。

【讨论】:

【参考方案7】:

是的,默认(包私有)访问级别。只需在你的类定义中省略任何访问修饰符,你就会得到你想要的。

【讨论】:

【参考方案8】:

大多数答案(包括接受的答案)都在谈论包私有。但这与 C# 中的 internal 相差甚远。

您只希望同一源根目录中的类访问同一源根目录中的另一个类,并且可能在不同的包(仍然在同一源根目录中)同时保持包私有,这在 Java 中是不可能的.如果您使用包私有,那么只有同一包中的类才能访问该资源。但是,即使同一个包中的下一级类(即该包下的另一个包)也无法访问该类。

 a.b.c.A --> class A
 a.b.c.d.B --> public class B

此处B 无法访问A。不幸的是,这迫使您将 A 标记为公开。

主要区别在于 C# 或 Java 打包编译代码的方式。 C# 可以将它们标记为内部(即不从程序集中导出符号),但 Java 打包为 jar 文件,并且导入 jar 的方式完全不同。


那么实际的解决方案是什么: 首先,没有强制解决方案。可以使用 javadocsannotations 将一个类标记为内部并阻止人们使用它,说明它是内部的并且可以进行很多更改,它不是一部分的公共 API,请不要使用它,否则如果您迁移到新版本可能会遇到麻烦...

我看到了两种方法:

    将您的包命名为内部:

    package org.mycoollib.api;
    /** This class is part of my public API*/
    public class A
      //...
    
    
    package org.mycoollib.internal;
    /** This an internal class, don't use it or your code might not
     work in a new release */
    public class B
      //...
    
    

一些现实生活中的例子:jdk.internalio.netty.util.internal 等等。当我看到 internal 作为包名时,我只是避免使用其中的类。

    使用注解实现与1中相同的目标

    package org.mycoollib.api;
    /** This class is part of my public API*/
    public class A
      //...
    
    
    package org.mycoollib.internal;
    /** This an internal class, don't use it or your code might not
     work in a new release */
    @Internal
    public class B
      //...
    
    

示例:android.annotation.SystemApi、org.apache.poi.Internal

甚至可能有一些库可以提供此类注释以及 maven 插件来在人们构建过程中发出警告。

因此,解决方案是思维方式:我们只是警告人们不要使用它,因为我们不保证它的名称和方法不会改变。如果他们仍然坚持使用它,那就这样吧。他们知道风险。

【讨论】:

以上是关于Java中有类似内部类的东西吗?的主要内容,如果未能解决你的问题,请参考以下文章

java中,匿名内部类可以使用外部类的成员变量吗

Swift 中的友元类(访问内部类的私有成员)

关于Java问题:“内部类可作为其他类的成员,而且可访问它所在类的成员”?

内部类访问外部类的变量必须是final吗,java静态方法中不能引用非静态变量,静态方法中不能创建内部类的实例

成员内部类的优点

Java——内部类详解