I have seen some references refer to a access modifier in Java called private protected (both words together):
private protected someMethod() {
}
One of the pages I found referring to this is here. My school lesson also referred to this access modifier (and said it exists). Using it, however, results in an error in the Java language.
I tried with both variables and methods and I'm pretty sure it doesn't exist, but I want an explanation of what happened. Was it considered, then rejected? Or did it get removed in a newer version of Java?
Edit: I am not looking for info about the protected keyword.
Removal of the access modifier
Java did originally have the private protected modifier, but it was removed in JDK 1.0.2 (the first stable version, the Java 1.0 we know today). A few tutorials regarding JDK 1.0.2 (here and here) say the following:
Note: The 1.0 release of the Java language supported five access levels: the four listed above plus private protected. The private protected access level is not supported in versions of Java higher than 1.0; you should no longer be using it in your Java programs.
Another answer on SoftwareEngineering.SE states:
Java originally had such a modifier. It was written private protected but removed in Java 1.0.
Now take a look at the Java Version History:
JDK 1.0
The first version was released on January 23, 1996 and called Oak. The first stable version, JDK 1.0.2, is called Java 1.
From this, we can conclude the tutorials regarding version 1.0.2 refer to the very first version, JDK 1.0, where the language was called Oak, but the one from SoftwareEngineering.SE refers to the first stable version, JDK 1.0.2 called Java 1.0, where it was removed.
Now if you try to search for it in the Java 1.0 documentation, you won't find it, because as mentioned earlier, it was removed in JDK 1.0.2, otherwise known as Java 1.0. This is proven again when you look at the "Last Modified" times for the link you posted. The link you posted was last modified in February of 1996. Java 1.0/JDK 1.0.2, when private protected was removed, was released after February of 1996, and according to the specification, August of 1996.
Reason for removal
Some sources also explain the reason for private protected, such as this one. To quote:
What was private protected?
Early on, the Java language allowed for certain combinations of modifiers, one of which was private protected. The meaning of private protected was to limit visibility strictly to subclasses (and remove package access). This was later deemed somewhat inconsistent and overly complex and is no longer supported.[5]
[5] The meaning of the protected modifier changed in the Beta2 release of Java, and the private protected combination appeared at the same time. They patched some potential security holes, but confused many people.
And the SoftwareEngineering.SE also supports this, by saying that it wasn't worth the inconsistencies and extra complexity, so it was removed early on.
Interpretation
My interpretation of all this is that maybe, back in the Oak days, both were allowed to coexist (hence the combination). Since protected's meaning had changed1, there may have been a need for allowing private and protected at the same time. The introduction became too complex and wasn't worth it, and was thus dropped in the end. By the time Java 1.0/JDK 1.0.2 rolled around, it had been dropped and thus cannot be found in the documentation.
1In the Oak Language Specification, Section 4.10, Access to Variables and Methods, it is noted that the default modifier was protected:
By default all variables and methods in a class are protected.
This is quite different from what we have today, the default package access. This may have paved the way for the need of private protected, because private was too restrictive and protected was too lenient.
There are confusing/unclear stories:
One, from the Princeton source you put, and also from MIT archives, states that:
Note: The 1.0 release of the Java language supported five access
levels: the four listed above plus private protected. The private
protected access level is not supported in versions of Java higher
than 1.0; you should no longer be using it in your Java programs.
But this feature is not specified on any official documentation for Java 1.0 here or here.
My guess is that this feature didn't make it to the official 1.0 version, since the official language specification is from August 1996 and Princeton source was last modified on February 1996.
PS: shame on Oracle for removing the archives for older versions.
As the link you provided in your question suggests private protected was used on an element/member of a class, when you want your subclass to be able access the element but keep it hidden from other classes in its package.
Java if compared to C++ has an extra concept of encapsulating elements - and that is a Package. One should also understand what is accessible within or outside a package in Java when it comes to these access-specifiers like private, public & protected.
Please note that I have explained why it was used. Not in current version of course
No, you can't use both private a protected together. Your tutorial is strange. What you do have is so called package private or in ot6 references package protected access. This is default access that is enabled when no acc6 qualifier is written explicitly.
Private scope is withing the existing class. Wherein Protected can be access within package and class extended by classes in other packages.
Seamlessly if you want your variable/methods to be access outside the package you need to define as protected/public otherwise private or some other access specifiers.
Protected methods are usually accessible from outside package and within sub-classes, i.e a class has to extend respective class to avail protected defined methods.
Private methods/variables have scope within the class.They cant be accessible outside the class.
Hence you can't define Private Protected at a same time!
Related
In clean code book, there is a point that says "Javadocs in Public APIs".
And the same for Effective java book, there is this item :
"Item 56: Write doc comments for all exposed API elements".
So this is my question "Are all public methods considered public APIs?"
They are different things for me.
Public API is the API that is announced and published to the world to use. So it is expected that many clients that you do not have control will use it. That also means it is more difficult to change as you need to consider the backward compatibility and that sort of thing if you want to make sure that any changes will not break the existing clients. Hence they should be well documented in javadocs to describe the actual behavior.
Pubic method is just a java method declared as public. You can declare a public method just for internal use , and it this case it is not the public API. Since it is only used internally , you have total control on the clients that use it .It is much more easy to change the API signature and its behaviour as you can change these clients to adapt to the new changes.
Also see this article for the distinction between published and public is actually more important than that between public an private.
A public API is exposed by means of public methods. A public method alone may not be an API. If the the question is if an API can be made of methods in "normal" classes that are not REST points, the answer is yes.
It depends.
An API is what a developer uses in order to achieve something
Are we talking about a Java library which does X ?
Well, any public method is part of the API.
An API can even be:
A set of solutions that allow the developer to achieve a certain result
Not necessarily a single public method produces a valuable output and it may be necessary in some cases to uses other methods to reach a meaningful output, still those procedures are part of the API.
I'd like to point out that an API (at least in Java) should be made of "public final" methods, because methods shouldn't be override by the caller. Clearly, we have to look at the context we are talking about, in some restricted cases you may want to allow it.
I have a really good source for you about this topic.
Recently i came across this video The art of building Java APIs: Do’s and Don’ts
made by Jonathan Giles (Java Guy at Microsoft) which explores the best and worst
practices about building API and it talks about Effective Java and covers some topics of the book.
(Those parts are highlighted while watching it).
Anyway, surely an interesting question.
In a (now) relatively old book, "Java Puzzlers", the authors talk about the inlining problems that can occur in static final fields (Puzzle 93: Class Warfare discussed here).
Essentially Java used to have a problem where due to how classes load, you could run into the issue that if a library class (class A) is recompiled with a changed static final field, then a class (class B) which uses that field might not function properly. This could happen because the class A field might have been inlined into class B during compilation, so that when the library is updated, class B does not incorporate the change in the class A field.
My simple question is... Is this still a problem? Do the newer versions of Java redefine the class loading procedure so that we do not have to worry about such issues?
I can only find relatively old posts touching on this issue (pre-2014), which makes me think that this issue has somehow been addressed, but I can find no definitive source.
Also, if it makes any difference, I am particularly interested if this will be a problem in Android.
I am thinking of the best way to manage package versioning in our project when have #deprecated annotation of some methods. We are using the maven-bundle-plugin, which either takes a package version from a packageinfo file or if there are no files, from the bundle-version.
We follow this convention about packages: ("X.Y.Z") where Z is growing when there is bug fix, Y is growing when there is new feature and X is growing when there is no compatibility.
So lets say we have package P with version ("1.0.0"). In P there is two classes Foo and Bar. If we have two methods in Foo - A() and B() and we have deprecated method A() and this are all changes in the hole package. How the package version is changing?
I'll refer to these version segments by their proper OSGi names: Major (your X), Minor (Y) and Micro (Z):
Major should be incremented when there is a breaking change that affects all users of the API;
Minor should be incremented when there is a new feature, which does not break consumers but it may break providers since they cannot automatically provide the new feature;
Micro should be incremented for any other change that does not cause any backwards compatibility issues.
Clearly adding #Deprecated to a method does not change the compatibility for either consumers or providers. Therefore this is a Micro change (in your example you should increment "Z"). It is at most a documentation change for the API.
in lucene 4.3.1 there was an interface StandardTokenizerInterface and a number of classes implement this class, such as StandardTokenizerImpl and ..... this interface doesn't exist in solr 5.3.1... what is the replacement of this class in solr 5.3.1?
The interface was not replaced, it was removed entirely, as it was deemed to no longer serve a useful purpose, due to the changes in how backwards compatibility is handled (instead of passing in a version arg, you would just use StandardTokenizer40, for instance). Ticket here: LUCENE-6000
The calls specified in the interface are still used in pretty much the same way by the current StandardAnalyzerImpl though, as far as I can tell.
In pre Java 5, there were no annotations. As a result you could not add metadata to a class.
To mark a class as serializable, you had to implement the Serializable interface (which is just that, a marker) and use further transient keywords to mark a field as non serializable if needed, something like:
public class MyClass implements Serializable {
...
private transient Bla field;
...
}
Now you could theoretically make use of annotations (this is a perfect use for them) and have:
#Serializable
public class MyClass {
...
#Transient
private Bla field;
...
}
But the interface and the keyword were not deprecated and no annotation was added in Java 5 to replace them.
What are the considerations for this decision to keep the interface and the keyword?
Off course there is the issue of compatibility with pre Java 5 code, but at some point that will end (e.g. related to the new features of generics, the JLS specifies that It is possible that future versions of the Java programming language will disallow the use of raw types). So why not prepare the way for serialized annotations also?
Any thoughts? (although I would prefer concrete references :D which I was unable to find)
The interface is there so methods can be defined to accept objects of type Serializable:
public void registerObject(Serializable obj);
Off course there is the issue of compatibility with pre Java 5 code ...
Yes. This is the root of the problem.
If they #deprecated the Serializable interface in (say) Java 5, then lots of old pre-Java 5 code would give warnings (or errors depending on compiler switches).
There's nothing actually wrong with using Serializable and "forcing" people to replace it is annoying. (People have better things to do ...)
When people have "fixed" this in their code, it will no longer compile using a pre-Java 5 compiler, or run on a pre-Java 5 JVM.
It is a bad idea to do things that make the compiler systematically "cry wolf".
... but at some point that will end.
In reality, the chance of this actually happening is (IMO) small. As far as I'm aware, Sun / Oracle have never removed a deprecated feature. Not even dangerous ones like Thread.stop() and friends.
As a footnote, the Go developers are taking a different approach to this problem. When they want to change a language or library feature, they just do it. They provide a converter that will automatically rewrite your code as required.
Serializable and transient are indeed two things that could have been replaced by annotations.
They haven't been deprecated probably because there are a lot of programs that use Serializable and it would have been annoying for millions if developers if the compiler would suddenly start spewing out thousands of deprecation warnings.
There are lots of other things in the standard Java API that could have been deprecated long ago - for example, the legacy collection classes Vector and Hashtable (and I'm sure you can easily find many more things). And there are other things that could have been implemented using annotations (for example the keyword volatile, strictfp and synchronized).
Deprecation is for things that are actively harmful. What you're suggesting is forcing authors of eight years of existing Java code (at the time) to rewrite it, for no advantage, just to shut up the deprecation compiler warnings, to get back to the fully correct code they had with Java 1.4. That would not be useful.