Given this code snippet, could you explain why it woks?
The thing is that the class constructor is marked private, so should not it prevent us to call it with new operator?
public class Alpha {
protected Alpha() {}
}
class SubAlpha extends Alpha {
private SubAlpha() {System.out.println("ok");}
public static void main(String args[]) {
new SubAlpha();
}
}
It all works because the static method is part of the class and it can see all private fields and methods, right? Outside this "new" initialization would never work?
The only private constructor in your question is SubAlpha, which SubAlpha itself is calling. There's no issue, a class can call its own private methods. The Alpha constructor is protected, so SubAlpha has access to it.
Edit: Re your edit: Yes, exactly. A separate class (whether a subclass or not) would not have access to SubAlpha's private constructor and could not successfully construct a new SubAlpha().
Example 1:
public class Beta
{
public static final void main(String[] args)
{
new SubAlpha();
// ^--- Fails with a "SubAlpha() has private access in SubAlpha"
// compilation error
}
}
Example 2:
public class SubSubAlpha extends SubAlpha
{
private subsubAlpha()
{
// ^== Fails with a "SubAlpha() has private access in SubAlpha"
// compilation error because of the implicit call to super()
}
}
This is, of course, constructor-specific, since scope is always member-specific. If a class has a different constructor with a different signature and a less restrictive scope, then a class using it (including a subclass) can use that other constructor signature. (In the case of a subclass, that would require an explicit call to super(args);.)
The code works as the main method is also in the same class. You may not be able to initialize SubAplha from a different class.
Related
Consider the following code:
public class A {
public static void main(String[] args) {
Runnable test1 = ((I)(new I() {}))::test; // compiles OK
Runnable test2 = ((new I() {}))::test; // won't compile
}
interface I {
private void test() {}
}
}
I don't really get the point... I understand that test() method is private. But what is changed if we cast an anonymous class to its interface ((I)(new I() {}))? More precisely I would like to see a particular JLS point which allows that trick.
P.S. I have reported it as a bug of compiler (ID : 9052217). It seems to me that Runnable test2 = ((new I() {}))::test; should be compiled fine in this particular case.
P.P.S. So far there was created a bug based on my report: https://bugs.openjdk.java.net/browse/JDK-8194998 . It might be that it will be closed as "won't fix" or whatsever.
This is not a new issue, and has nothing to do with private interface methods or method references.
If you change code to extend a class instead of implement an interface, and to call the method instead of referencing it, you still get exact same problem.
class A {
public static void main(String[] args) {
((I)(new I() {})).test(); // compiles OK
((new I() {})).test(); // won't compile
}
class I {
private void test() {}
}
}
However, that code can be applied to older Java versions, and I tried Java 9, 8, 7, 6, 5, and 1.4. All behave the same!!
The issue is that private methods are not inherited1, so the anonymous class doesn't have the method, at all. Since the private method doesn't even exist in the anonymous class, it cannot be called.
When you cast to I, the method now exists for the compiler to see, and since I is an inner class, you are granted access (through a synthetic method), even though it is private.
In my opinion, it is not a bug. It's how private methods work in context of inheritance.
1) As found by Jorn Vernee in JLS 6.6-5: "[A private class member] is not inherited by subclasses".
private methods are not inherited (Closest I found so far is: JLS6.6-5: "[A private class member] is not inherited by subclasses"). That means that you can not access a private method, from a subtype (because it simply does not 'have' that method). For instance:
public static void main(String[] args) {
I1 i1 = null;
I2 i2 = null;
i1.test(); // works
i2.test(); // method test is undefined
}
interface I1 {
private void test() {}
}
interface I2 extends I1 {}
That also means that you can not directly access the test method through the type of an anonymous subclass.
The type of the expression:
(new I() {})
Is not I, but actually the non-denotable type of the anonymous subclass, so you can't access test through it.
However, the type of the expression:
((I) (new I() {}))
is I (as you explicitly cast it to I), so you can access the test method through it. (just like you can do ((I1) i2).test(); in my above example)
Similar rules apply to static methods, as they are also not inherited.
Invoking a private method is only possible through an expression of exactly the declaring type, regardless of the scenario.
Let’s explain it with the simplest example
public class A {
public static void main(String[] args) {
B b = new B();
b.someMethod(); // does not compile
A a = b;
a.someMethod(); // no problem
}
private void someMethod() {}
}
class B extends A {
}
You might expect this to compile using b.someMethod() to invoke A’s someMethod(). But what if B was declared as
class B extends A {
public void someMethod() {}
}
This is possible, as the private void someMethod() is not inherited, so public void someMethod() does not override it. But it should be clear that now b.someMethod() should invoke B’s method.
So if it was allowed that b.someMethod() ends up at a private method of A, it would depend on whether B declares another someMethod(), at which actual method the call will end up. And that obviously contradicts the entire concept of private methods. private methods are not inherited and never overridden, so it should not depend on the subclass, whether a call ends up at a private method or a subclass’ method.
Your example is similar. The anonymous inner class that implements I could declare its own test() method, e.g. Runnable test2 = ((new I() {void test() {}}))::test; so it would depend on that anonymous inner class, whether the private method of I or a method of that anonymous inner class gets invoked, which would be unacceptable. Of course, with such an inner class, directly preceding the invocation or method reference, a reader can immediately tell, at which method the invocation will end up, but it would be very inconsistent, if this was allowed for an anonymous inner class but nothing else.
The private method of I is accessible to A as it is a the nested interface, but as shown with the simpler example above, the rule is not about accessibility, as the rule even applies when the private method is within the same class as the caller.
This is counter-intuitive. First let's simplify this a bit:
static interface Inter {
private void test() {
System.out.println("test");
}
}
public static void main(String[] args) {
((Inter) new Inter() {
}).hashCode();
}
This makes sense as you are calling the public hashCode method, here is the (important part only) byte code for it:
public static void main(java.lang.String[]);
Code:
0: new #2 // class com/test/DeleteMe$1
3: dup
4: invokespecial #3 // Method com/test/DeleteMe$1."<init>":()V
7: invokevirtual #4 // Method java/lang/Object.hashCode:()I
10: pop
11: return
Looks very sane to me. Now let's change that to calling test():
public static void main(String[] args) {
((Inter) new Inter() {
}).test();
}
The byte code for this:
invokestatic #4 // InterfaceMethod com/test/DeleteMe$Inter.access$000:(Lcom/test/DeleteMe$Inter;)V
Since private methods are not inherited, you are actually "going" to that method via the access$n static synthetic method.
In the below example why does the String b prints null and String c prints "gg".
Correct me if I am wrong, whenever a subclass (BClass) overrides a protected method (i.e initClass()) of the superclass (AClass).If you instantiate the subclass. The superclass must make use of overriden method specified by the subclass.
public class Example {
public class AClass {
private String a;
public AClass() {
initClass();
}
protected void initClass() {
a = "randomtext";
}
}
public class BClass extends AClass {
private String b = null;
private String c;
#Override
protected void initClass() {
b = "omg!";
c = "gg";
}
public void bValue() {
System.out.println(b); // prints null
System.out.println(c); // prints "gg"
}
}
public static void main(String[] args) {
Example.BClass b = new Example().new BClass();
b.bValue();
}
}
As of the JSF 12.5
In the example you can see the execution order. The first steps are the callings of the Constructor down to the Object constructor.
Afterwards this happens:
Next, all initializers for the instance variables of class [...] are executed.
Since your instance variable b is initialized to null it will be null again afterwards
This is happening because the superclass constructor is called before the fields of ClassB is initialized. Hence the initClass() method is called which sets b = "omg!" but then again when the super class constructor returns, b is initialized to the value declared in ClassB which is null.
To debug, put a break point and go step by step, you will find that b is first set to null and then changes to omg! and then comes back to null.
There have been already given several correct answers about what's happening. I just wanted to add that it is generally bad practice to call overridden methods from constructor (except of course if you know exactly what you are doing). As you can see, the subclass may not be completely initialised at the time its instance method is invoked (subclass constructor logic has not been executed yet, so effectively overridden method is invoked on an unconstructed object which is dangerous) which might lead to confusions like the one described in this question.
It is much better to write initialisation logic in the constructor and if it is too long then divide it between several private methods invoked from the constructor.
This is happening like this because, first constructor of AClass, which set value of b = omg! and c=gg. After that When BClass gets load in memory it set b=null and c remain as it is which is gg, this is happening because, because in BClass, for b you are doing declaration as well as initialization and for c you are doing only declaration, so as c is already in the memory it even won't get it's default value and as you are not doing any initialization for c, it remain with it's earlier state.
I believe that this example explains the issue:
public class Main {
private static class PrintOnCreate {
public PrintOnCreate(String message) {
System.out.println(message);
}
}
private static class BaseClass {
private PrintOnCreate member =
new PrintOnCreate("BaseClass: member initialization");
static {
System.out.println("BaseClass: static initialization");
}
public BaseClass() {
System.out.println("BaseClass: constructor");
memberCalledFromConstructor();
}
public void memberCalledFromConstructor() {
System.out.println("BaseClass: member called from constructor");
}
}
private static class DerivedClass extends BaseClass {
private PrintOnCreate member =
new PrintOnCreate("DerivedClass: member initialization");
static {
System.out.println("DerivedClass: static initialization");
}
public DerivedClass() {
System.out.println("DerivedClass: constructor");
}
#Override
public void memberCalledFromConstructor() {
System.out.println("DerivedClass: member called from constructor");
}
}
public static void main (String[] args) {
BaseClass obj = new DerivedClass();
}
}
The output from this program is:
BaseClass: static initialization
DerivedClass: static initialization
BaseClass: member initialization
BaseClass: constructor
DerivedClass: member called from constructor
DerivedClass: member initialization
DerivedClass: constructor
... which demonstrates that the derived class's members are initialized after the base class's constructor (and the invocation of the derived class's member function have completed). This also demonstrates a key danger of invoking an overridable function from a constructor, namely that the function can be invoked before the members of the class on which it depends have been initialized. For this reason, constructors should generally avoid invoking member functions (and, when they do, those functions should either be final or static, so that they either depend only on the current class which has been initialized or on none of the instance variables).
I'm a begginer programmer for Android and I found some code over the internet and I couldn't get what this "Class not meant to be instantiated" means?! Also what's the use of it. I would be very happy if somebody could help here.
public class Settings
{
//some code
private Settings() {} // Class not meant to be instantiated
//some code
}
The constructor is private so only the class itself can create instances. There are several reasons for doing this. A couple off the top of my head...
The class is a "utility" class that only contains static methods and so instantiating it would make no sense. As the class is commented "Class not meant to be instantiated" I guess this is the most likely reason.
The class itself controls its own lifecycle and provides methods for creating instances. For example if the class is a lazy singleton it might provide a method that creates an instance when first called and return this instance on subsequent calls.
It is a private constructor. This means that outside classes cannot create new instances using the default constructor.
A little more info
All Objects in Java have a default constructor:
public MyObject() {}
That is how you can have this class:
public class MyObject{}
and still be able to call:
MyObject mObj = new MyObject();
Private Constructors
Sometimes a developer may not want this default constructor to be visible. Adding any other constructor will nullify this constructor. This can either be a declared constructor with empty parameters (with any of the visibility modifiers) or it can be a different constructor all together.
In the case above, it is likely that one of the following models is followed:
The Settings object is instantiated within the Settings class, and is where all the code is run (a common model for Java - where such a class would also contain a static main(String[] args) method).
The Settings object has other, public constructors.
The Settings object is a Singleton, whereby one static instance of the Settings Object is provided to Objects through an accessor method. For example:
public class MyObject {
private static MyObject instance;
private MyObject(){}//overrides the default constructor
public static MyObject sharedMyObject() {
if (instance == null)
instance = new MyObject();//calls the private constructor
return instance;
}
}
This inner construct
private Settings() {}
is a constructor for Settings instances. Since it is private, nobody can access it (outside of the class itself) and therefore no instances can be created.
The constructor is private so its not meant to be called by anything outside of the class
It's not a nested class, it's a constructor. A private constructor means that you can't construct instances of this class from outside, like this:
Settings s = new Settings(); //Compilation error! :(
Now, if a class can't be instantiated, what could it be for? The most likely reason for this is that the class would return instances of itself from a static method, probably as a singleton. The settings are normally global to the program, so a singleton pattern really fits here. So there would be a static method that goes kind of like this
static private TheOnlySettings = null;
static public getSettings()
{
if(TheOnlySettings == null)
TheOnlySettings = new Settings(); //Legal, since it's inside the Settings class
return TheOnlySettings;
}
See if that's indeed the case.
As other have mentioned, a class having private constructors cannot be instantiated from outside the class. A static method can be used in this case.
class Demo
{
private Demo()
{
}
static void createObjects()
{
Demo o = new Demo();
}
}
class Test
{
public static void main (String ...ar)
{
Demo.createObjects();
}
}
We can have private constructor . Below program depicts the use of private constructor with a static function
class PrivateConstructor {
private:
PrivateConstructor(){
cout << "constructor called" << endl;
}
public:
static void display() {
PrivateConstructor();
}
};
int main() {
PrivateConstructor::display();
}
Isn't that subclass inherits everything from superclass true? But subclass could not access its superclass's private attribute/method, but can access its own. So I wrote a test program. But it seems subclass has not one!
class a {
private void set() {
System.out.println("a.set()");
}
}
public class b extends a {
// private void set() {
// System.out.pritln("b.set()");
// }
void f() {
set();
}
public static void main(String[] args) {
b b = new b();
b.f();
}
}
If I comment out the set() method in b as the example does, it won't compile.
Any idea? Any explanation from JVM view ?
Yes, private methods aren't accessible from a derived class. protected and public are.
When you declare set in your derived class, you gain access to this derived version since it's now part of the class (no longer a private base class method).
You'd still get an error if you attempted to call super.set().
Edit: the trick aroth's talking about I assume is reflection. :) Don't.
The question is meaningless. Private is private. Invisible to everything outside the current class. If you want 'protected', use it.
If you want something in between, use the "protected" modifier instead of the "private" modifier; protected essentially means private to everything but subclasses.
I have the following problem in Java:
I have a base class and a derived class and I have a method in the base class. When I call the Base's foo method through Derived I want to get the Derived's class. The foo method can be generic if it can be done that way.
class Base
{
static void foo()
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo();
Thanks for your help!
David
That's not the way that static methods work. You'll have to implement Derived.foo(), do whatever it is that's special to Derived, and that method then calls Base.foo(). If you really need the type information, you could create Base.foo0(Class klass).
But to be honest, any static method that needs to know that type of the class that it's invoked on should probably be an instance method.
Well, the caller of Derived.foo() knows what they are calling, so you could alter your methods thus:
class Base
{
static void foo(Class< T > calledBy)
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo(Derived.class);
static methods are not inheritated. Static methods with the same signature can only hide similar methods in the superclass. This means that you never will see the result you probably want - you always exactly know the enclosing class. It is never possible that the static method is somehow "within" another class. So it is just impossible to produce the desired result. Calling a static method from a subclass or an instance is a bad idea for this reason as it just hides the real class. (IDEs and static code analysis tools can mark or correct this.)
Sources:
JLS http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#227961
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
So what works with inherited methods does not work with static methods that are not inherited.
class Base {
static void foo() {
// Only the static context is available here so you can't get class dynamic class information
}
void bar() {
System.out.println(getClass());
}
}
class Derived extends Base {
}
class Another extends Base {
static void foo() {
// No super call possible!
// This method hides the static method in the super class, it does not override it.
}
void bar() {
super.bar();
}
}
Derived derived = new Derived();
derived.bar(); // "class Derived"
Base base = new Base();
base.bar(); // "class Base"
// These are only "shortcuts" for Base.foo() that all work...
derived.foo(); // non-static context
Derived.foo(); // could be hidden by a method with same signature in Derived
base.foo(); // non-static context
Base.foo(); // Correct way to call the method
Another a = new Another();
a.foo(); // non-static context
Another.foo();
Is it good idea that the language allows this? - Hm. I think it is telling that IDEs and code analysis tools warn and can even correct this automatically.
Not possible, Derived.foo() will simply give code for Base.foo().
Derived.foo();
This will go to foo defined in Derived, if one is defined there:
class Base {
static void foo() {
System.out.println("Base");
}
}
class Der extends Base {
static void foo() {
System.out.println("Der");
}
}
class Check {
public static void main(String[] args) {
Base.foo();
Der.foo();
}
}
When I run it:
javac -g Check.java && java Check
Base
Der
So what is your question? If you to require that each derived class implement foo that is not possible to enforce in Java.