Java 中包私有类的优缺点?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6470556/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pros and cons of package private classes in Java?
提问by zw324
I am learning Java recently, and I came across the notion of package-private
classes, which is the default if we don't specify anything. But then I realized:
我最近在学习 Java,我遇到了package-private
类的概念,如果我们不指定任何东西,这是默认的。但后来我意识到:
I seldom see the use of package-private class. Is there a reason for this, e.g., it has serious drawbacks, it is redundant, or simply I am not reading enough? Are there strong arguments for/against its usage?
If it is really not useful in most cases, why would it be the default?
In what situation should we use package-private in the real world? I.e., when would it become irreplaceable?
我很少看到包私有类的使用。这是否有原因,例如,它有严重的缺点,它是多余的,或者只是我读得不够?是否有强有力的论据支持/反对它的使用?
如果在大多数情况下它真的没有用,为什么它会成为默认值?
在现实世界中我们应该在什么情况下使用 package-private ?即,它什么时候会变得不可替代?
In other words, what are the major pros and cons of the default package-private modifier?
换句话说,默认 package-private 修饰符的主要优点和缺点是什么?
采纳答案by Andrzej Doyle
The short answer is - it's a slightly wider form of private.
简短的回答是——这是一种稍微宽泛的私有形式。
I'll assume that you're familiar with the distinction between public
and private
, and why it's generally good practice to make methods and variables private
if they're going to be used solely internally to the class in question.
我假设你熟悉的区别public
和private
,以及为什么它通常是很好的做法,使方法和变量private
,如果他们要单独用于内部问题的类。
Well, as an extension to that - if you're thinking about creating your software in a modular way, you might think about a public interface to your module, which will have multiple classes inside it collaborating between themselves. In this context it makes perfect sense to make methods public
if they're going to be called by consumers; private
if they're internal to a class; and package private
if they're used to call between classes in this module, i.e. it's an implementation detail of your module (as seen by public callers) but spans several classes.
好吧,作为对此的扩展 - 如果您正在考虑以模块化方式创建软件,您可能会考虑到模块的公共接口,其中将有多个类在它们之间进行协作。在这种情况下,public
如果消费者要调用方法,则创建方法是非常有意义的。private
如果它们是一个类的内部;而package private
如果他们在此模块中用来调用类之间,也就是说,它是你的模块的实施细节,但跨越几个类(公共呼叫者可以看到)。
This is seldom used in practice, because the package system turns out to not be so useful for this sort of thing. You'd have to dump all of the classes for a given module into exactly the same package, which for anything non-trivial is going to get a bit unwieldy. So the idea is great - make a method accessible to just a handful of "nearby" classes, as a slightly wider private
- but the restrictions on how you define that set of classes means it's rarely used/useful.
这在实践中很少使用,因为包系统对这类事情不是那么有用。您必须将给定模块的所有类转储到完全相同的包中,这对于任何非平凡的事情都会变得有点笨拙。所以这个想法很棒——让一个方法只能被少数“附近”的类访问,作为一个稍微宽一点的private
——但是对如何定义这组类的限制意味着它很少使用/有用。
回答by BZ.
1 - Depends on the architecture -Generally if you are writing code just for yourself and on small projects you probably wouldn't use it. In larger projects it can be helpful to ensure that you can control where and how certain methods are called.
1 - 取决于架构 - 通常,如果您只是为自己和小型项目编写代码,您可能不会使用它。在较大的项目中,确保您可以控制调用某些方法的位置和方式会很有帮助。
2 - Default (I.e. not public/protected/private) is not the same as private - its a 4th state. See Java Access Control
2 - 默认(即非公共/受保护/私有)与私有不同 - 它是第 4 种状态。请参阅Java 访问控制
3 - It can make life easier when you're writing libraries that you don't want third parties relying on how you are implementing the underlying code - you just make the API itself public.
3 - 当您编写不希望第三方依赖于您如何实现底层代码的库时,它可以使生活更轻松 - 您只需将 API 本身公开即可。
回答by jtoberon
Regarding the question of "why would it be the default,", in this context, the term "default" just means the absence of another qualifier. I guess they could have invented another keyword ("package" was already taken), but they didn't.
关于“为什么会是默认值”的问题,在这种情况下,“默认值”一词仅表示没有其他限定词。我猜他们本可以发明另一个关键字(“包”已经被采用了),但他们没有。
In the real world, I use default access for utility classes and abstract classes that I don't want people to call or otherwise use from other packages. Let's say you have an interface and two concrete implementations that extend from some abstract class. You declare your two concrete classes as final because you don't necessarily want people to subclass them (see Effective Java). You also don't want people to monkey around with your abstract class for the same reason. If you use default access for the abstract class, then people only see it if they put their class in your package. It's not bullet proof, but I think it's a reasonable use/illustration of default access. That said, the fact that it does not prevent the details from leaking as private would, i.e. doesn't guarantee anything, means that it's not a particularly useful convention.
在现实世界中,我对实用程序类和抽象类使用默认访问权限,我不希望人们从其他包调用或以其他方式使用它们。假设您有一个接口和两个从某个抽象类扩展的具体实现。您将两个具体类声明为 final,因为您不一定希望人们对它们进行子类化(请参阅 Effective Java)。出于同样的原因,您也不希望人们在您的抽象类上胡闹。如果您对抽象类使用默认访问权限,那么人们只有将他们的类放入您的包中才能看到它。这不是防弹的,但我认为这是默认访问的合理使用/说明。也就是说,事实上它不会像私人那样防止细节泄露,即不保证任何事情,这意味着它'
Another reason why you haven't see it used more often is that people tend to exclude classes with default access from their javadocs.
您没有看到它更频繁使用的另一个原因是人们倾向于从他们的 javadoc 中排除具有默认访问权限的类。
回答by umlcat
"Package Private" its used when you have several packages, and it means, other classes in the same package can access that class or class member as "public", classes in other packages cannot access, its like "private like them."
“Package Private”当你有多个包时使用,它的意思是,同一个包中的其他类可以作为“public”访问该类或类成员,其他包中的类不能访问,就像“像他们一样私有”。
回答by David
One nice thing about package-private is that you can use it to give access to methods you would otherwise consider private to unit test classes. The downside of course being that other classes in the package could call it when they really shouldn't.
package-private 的一个好处是,您可以使用它来访问那些原本认为是单元测试类私有的方法。缺点当然是包中的其他类可以在它们真正不应该调用它时调用它。
回答by AbdelRahman Shabana
Please notice that when you are speaking about classes you have only two options:
请注意,当您谈论类时,您只有两种选择:
- public classes
- package private classes
- 公开课
- 打包私人课程
The concept of "private class" is meaningless. (Why to make a class that is not used anywhere?!)
“私人课堂”的概念毫无意义。(为什么要创建一个在任何地方都不使用的类?!)
So if you have a class for intermediate operations that needn't to be exposed to API users you are supposed to declare it as "package private"
因此,如果您有一个不需要向 API 用户公开的中间操作类,您应该将其声明为“包私有”
Also when you define many classes in the same source file, only one class is allowed to be public (its name matched the .java file name). If any other class is defined in the same file it must be "package private".
此外,当您在同一个源文件中定义多个类时,只允许一个类是公共的(其名称与 .java 文件名匹配)。如果在同一文件中定义了任何其他类,则它必须是“包私有的”。
回答by assylias
Apart from encapsulation, one of the main advantages of using package-private classes is that they do not appear in the javadoc of your project. So if you use some helper classes which have no other use but to help your public classes do something clients need, it makes sense to make them package private as you want to keep things as simple as possible for users of the library.
除了封装之外,使用包私有类的主要优点之一是它们不会出现在项目的 javadoc 中。因此,如果您使用一些没有其他用途的辅助类,只是为了帮助您的公共类做客户需要的事情,那么将它们打包是有意义的,因为您希望让库的用户尽可能简单。
As an example, you can have a look at a library that I have developed. The javadoconly contains 5 interfaces and 12 classes although the source codehas a lot more. But what is hidden is mostly internal layers that provide no added-value for a client (typically all the abstract base classes are hidden).
例如,您可以查看我开发的一个库。尽管源代码有更多,javadoc只包含 5 个接口和 12 个类。但是隐藏的主要是内部层,它们没有为客户端提供附加值(通常所有抽象基类都隐藏了)。
There are also many examples in the JDK.
JDK中也有很多例子。
回答by icza
The package-private access level is more restrictive than protected
: protected attributes and methods can still be accessed by simply subclassing a class. Protectedmembers are (or may be) intended for inheritance while package-private members are not.
包私有访问级别比protected
以下限制更多:通过简单地子类化一个类仍然可以访问受保护的属性和方法。受保护的成员(或可能)用于继承,而包私有成员则不是。
Package-private members are often used so multilpe classes inside a package can access implementation-specificattributes or (utility) methods.
包私有成员经常被使用,因此包内的 multilpe 类可以访问特定于实现的属性或(实用程序)方法。
Good examples to this are the package-private constructor of String
and the StringBuilder.value
char array:
很好的例子是包私有构造函数String
和StringBuilder.value
char 数组:
/*
* Package private constructor which shares value array for speed.
* this constructor is always expected to be called with share==true.
* a separate constructor is needed because we already have a public
* String(char[]) constructor that makes a copy of the given char[].
*/
String(char[] value, boolean share) {
// assert share : "unshared not supported";
this.value = value;
}
So classes inside the java.lang
package can efficiently create new Strings
if the content is already present in a char[]
without compromising security. You cannot do this from your application because if you could, you would have access (reference) to the internal char array of a String
which is immutable (reflection not counted!).
因此,如果内容已经存在于java.lang
包中,则包内的类可以有效地创建新Strings
的,char[]
而不会影响安全性。您不能从应用程序执行此操作,因为如果可以,您将可以访问(引用)String
不可变的 a 的内部字符数组(反射不计入!)。
In StringBuilder
(or rather AbstractStringBuilder
where the implementation comes from) the char array holding the current value char[] value
and an accessor method to this char[] getValue()
are also package-private so various utility methods of String
like contentEquals(StringBuffer sb)
and contentEquals(CharSequence cs)
can utilize this for efficiency and faster comparisons without exposing the internal char array to the "world".
在StringBuilder
(或者说AbstractStringBuilder
,其中的执行来自)char数组保持的电流值char[] value
和存取方法本char[] getValue()
也包私人的,从而各种实用方法String
等contentEquals(StringBuffer sb)
并contentEquals(CharSequence cs)
可以利用该对效率和更快的比较而无需内部char数组暴露于世界”。