44

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

4

8 回答 8

60

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

package com.sample;

class MyPackagePrivateClass
{
    ...
}
于 2011-05-12T16:18:53.220 回答
11

删除访问修饰符类似于 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;
    }
}

爪哇

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

于 2011-05-12T16:19:32.517 回答
9

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

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

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

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

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

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

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

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

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

于 2016-11-05T10:34:26.840 回答
2

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

package com.blah; class Foo{ }

于 2011-05-12T16:19:43.400 回答
1

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

public=任何人都可以访问

private=只能在当前类中访问

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

默认=可在包内访问

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

于 2011-05-12T16:25:57.980 回答
1

大多数答案(包括接受的答案)都在谈论包私有。但这远非internalC# 中的。

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

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

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

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


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

我看到了两种方法:

  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 */
    public class B{
      //...
    }
    

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

  1. 使用注释来实现与中相同的目标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.SystemApiorg.apache.poi.Internal

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

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

于 2021-12-09T10:28:17.940 回答
0

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

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

于 2011-05-12T16:19:48.920 回答
0

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

于 2011-05-12T16:20:04.750 回答