While reading Reflection API i got this "Every Java Type has a class Instance And the class instance itself has no public Constructor" .
Now this is really confusing for me. Because what i have read till now says . All classes have constructor even when we don't specify any, we get constructor by default (even if the class is static) once we create its instance. Can someone explain me this in simple word
(to show even static class has constructor)
public class Reader1 {
private int pageNumber;
private class ReaderName1{
public int getPage(){
return pageNumber;
}
}
static class ReaderFound{
}
}
using javap
class Reader1$ReaderFound {
Reader1$ReaderFound();
}
It says: no public constructor. That doesn't mean it has no constructor at all. It does have a private constructor, which you can also create, as below given class, which also doesn't have a public constructor.
class Test {
private Test() { }
}
"Every Java Type has a class Instance And the class instance itself has no public Constructor" that's means the java.lang.Class has no public constructor because Only the JVM can create the java.lang.Class instance ,and every class Java Type has a java.lang.Class instance.i think that is reason why you were confused.
In Java you can suppress a public constructor by defining it private in the inheriting class - for Class this means:
public final class Class<T> {
private Class() {
//this constructor is private, no other constructor exists or will be generated
}
}
To create an instance of class there exist some factory methods, like Class.forName.
Directly cited from the official website. I hope it can help you.
The primitive Java types (boolean, byte, char, short, int, long, float, and double), and the keyword void are also represented as Class objects.
Class has no public constructor. Instead a Class object is constructed automatically by the Java Virtual Machine when a class loader invokes one of the defineClass methods and passes the bytes of a class file.
https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html
Related
The text of an exercise from a well known and basic Java programming textbook follows:
'Sometimes we would like a class that has just a single unique instance. Create a class Merlin that has one attribute, theWizard, which is static and of type Merlin. The class has only one constructor and two methods, as follows:
* Merlin —a private constructor. Only this class can invoke this construc-
tor; no other class or program can create an instance of Merlin
* summon —a static method that returns theWizard if it is not null; if theWizard is null, this method creates an instance of Merlin using the private constructor and assigns it to theWizard before returning it.
* consult—a non-static method that returns the string "Pull the sword
from the stone" '
Were you able to understand what the author is asking in the point 'Merlin -a private constructor' ? I know what a constructor is as well as what a private method is. But here what's the answer ? I thought of something like
public class Merlin {
private static Merlin theWizard;
/*public Merlin()
{
???
}*/
private Merlin()
{
this();
}
public static Merlin summon(Merlin theWizard) {
if (theWizard == null) {
theWizard = new Merlin();
return theWizard;
}
public String consult() {
return "Pull the sword from the stone";
}
}
and of course JavaBeans says 'private Merlin()' is recursive. So what do I do ? The next exercise is related to the above one and could help you to understand what the answer is; here it is:
Create a program that tests the class Merlin described in the previous exercise.
Use the toString method to verify that a unique instance has been created.
Thank you very much for all that you will be able to tell me.
This is an instance of the Singleton Pattern; in your case, just replace this() with super() to use the superclass's constructor (technically, if you don't place a super constructor call, the compiler will insert one for you; so you could just remove it).
Food for thought:
why is the Merlin class private?
why is the Merlin class static?
where's the rest of your code?
Get rid of this():
public class Merlin {
private static Merlin theWizard;
private Merlin() {}
...
}
this followed by parens is the syntax used to call a constructor of the same class, since you are not specifying any arguments inside the parens then you're referring to the no-argument instructor, which is the constructor this is being called from, so the constructor would call itself recursively until it runs out of stack space. The IDE is checking for this problem and trying to warn you about it.
Calling super() in the constructor is allowed (it calls the no-argument constructor in the superclass, which here is java.lang.Object) but not required, the compiler will insert a call to super if you don't.
By the way you can't have multiple overloads of a constructor or method with the same argument list. You can't have a public no-arg constructor and a private no-arg constructor.
The author is trying to describe a class that has control over how its instances are created, it makes its constructor private so that only the class itself is allowed to instantiate an object of that class.
How is the compiler not complaining when I write the following code?
public class MyClass
{
private int count;
public MyClass(int x){
this.count=x;
}
public void testPrivate(MyClass o){
System.out.println(o.count);
}
}
Even though it is an instance of the same class in which testPrivate is written, shouldn't it give a compilation error at System.out.println(o.count)? After all, I am trying to access a private variable directly.
The code even runs fine.
A private member is accessible from any method within the class in which it is declared, regardless of whether that method accesses its own (this) instance's private member or some other instance's private member.
This is stated in JLS 6.6.1:
...Otherwise, if the member or constructor is declared private, then access is permitted if and only if it occurs within the body of the top level class (§7.6) that encloses the declaration of the member or constructor.
This feature of Java allows you to write methods that accept an instance of the class as an argument (for example - clone(Object other), compareTo(Object other)) without relying on the class having non private getters for all the private properties that need to be accessed.
Private fields are private to the class as a whole, not just to the object.
Other classes do not know that MyClass has a field called count; however, A MyClass object knows that another MyClass object has the count field.
Accessors are not security! They are encapsulation, to keep others from having to know about the code.
Consider if someone wrote a Quantum Bogo Sort, but disappeared once he quashed the last bug -- understanding the code causes one to be either deleted from the universe or to go mad.
Despite this minor drawback, if properly encapsulated, this should become your prefered sorting algorithm, as all fields and methods except Sort should be private.
You don't know how it works, and you don't want to know how it works, but it works and that's enough. If on the other hand, everything is public, and you have to understand how it does what it does to use it correctly -- that's just too much bother, I'll stick with quicksort.
Though it is the instance of the same class in which testPrivate is
written, but shouldn't it through a compiler error at
System.out.println(o.count);
No. It will never throw a compilation error.
This is much similar to what a simple getter and setter does or a copy constructor does. Remember we can access private members using this.
public MyClass {
private String propertyOne;
private String propertyTwo;
// cannot access otherObject private members directly
// so we use getters
// But MyClass private members are accessible using this.
public MyClass(OtherClass otherObject) {
this.propertyOne = otherObject.getPropertyOne();
this.propertyTwo = otherObject.calculatePropertyTwo();
}
public void setPropertyOne(String propertyOne) {
this.propertyOne = propertyOne;
}
public String getPropertyOne() {
return this.propertyOne;
}
}
Your testPrivate method accepts an instance of MyClass. Since testPrivate is a method inside MyClass, it will have access to private properties.
public void testPrivate(MyClass o) {
this.propertyOne = o.propertOne;
}
Methods defined inside the class will always have access to it's private members, through this. and instance variable.
But if you define testPrivate outside of MyClass then, you won't have access to private members. There you will have to use a method or a setter or a getter.
Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. Check the official documentation
The following is my ProtectedConstructor.java source code:
package protectCon;
public class ProtectedConstructor{
public int nothing;
ProtectedConstructor(){
nothing = 0;
}
}
And following is the UsingProtectedCon.java source:
package other;
import protectcon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{ //**Line 4**
public static void main(String... a) {
}
}
When I compile UsingProtectedCon.java, I get error at Line 4 shown above. It says that ProtectedConstructor() is not public ; so cannot be accessed outside package.
However, since my class is public, shouldn't I be able to extend it outside package. I am anyway not creating any instance of it.
Now, if I make the constructor of ProtectedConstructor class as public or protected then the code compiles fine with no error.
So then why is it necessary even for the constructor to be public or protected, and not just have default access?
If you want to extends a class outside its package it must have a constructor that is public or protected because in Java every constructor must call a constructor from its superclass.
Because of this there is an implied super() call in every constructor which does not have this() or an explicit call to super() as its first statement. And if you don't specify a constructor at all Java will add a default parameterless constructor, so in effect your code looks like this:
public class UsingProtectedCon extends ProtectedConstructor {
public UsingProtectedCon() {
super();
}
public static void main(String... a) {
}
}
So in other words your code is failing to compile because the call to super() in the default constructor cannot be resolved.
constructor is a member of class like field and method so access modifier applies to it in the same manner it apples to all the member of class
when you extend the class A in B , A's its default constructor will get called from B's constructor implicitly (if you don't call any of the overloaded constructor)
in your class ProtectedConstructor is defined with Package-Private access
This means that outside the package its not seen even by the classes that extend from your ProtectedConstructor class
Define your constructor with 'protected' access modifier instead and you'll be done:
package protectCon;
public class ProtectedConstructor{
public int nothing;
protected ProtectedConstructor(){
nothing = 0;
}
}
Your constructor is not public. Default scope is package-private.
JLS 6.6.7 answers your question. A subclass only access a protected members of its parent class, if it involves implementation of its parent. Therefore , you can not instantiate a parent object in a child class, if parent constructor is protected and it is in different package.Since the default constructor of the subclass would try to call parent class constructor ,you got this error.
See this SO Post for details
to avoid all confusion do it like this.
package protectCon;
public class ProtectedConstructor{
public int nothing;
public ProtectedConstructor(){
nothing = 0;
}
}
package other;
import protectCon.ProtectedConstructor;
public class UsingProtectedCon extends ProtectedConstructor{ //**Line 4**
public UsingProtectedCon(){
super();
}
public static void main(String... a){
}
}
You can have constructors which are public, protected (for internal used) and even private.
A simple example is String which has public constructors for general use and package-local constructors for internal use.
The ObjectOutputStream class has a public constructor which takes an OutputStream and a protected constructor which can only be used by a sub-class.
BTW: if you have an abstract class, does it make sense to make the constructor public as if often the case. ;) hint: it is the same as protected.
If child will have constructor which is private in parent,we can make child's instance with that constructor and cast it to parent's type.
So to prevent this java compiler is not allowing constructor to have constructor which is private in parent.
In Java, I can't create instances of abstract classes. So why doesn't eclipse scream about the following code?
public abstract class FooType {
private final int myvar;
public FooType() {
myvar = 1;
}
}
The code is fine, the final variable is initialized in the constructor of FooType.
You cannot instantiate FooType because of it being abstract. But if you create a non abstract subclass of FooType, the constructor will be called.
If you do not have an explicit call to super(...) in a constructor, the Java Compiler will add it automatically. Therefore it is ensured that a constructor of every class in the inheritance chain is called.
You can have constructors, methods, properties, everything in abstract classes that you can have in non-abstract classes as well. You just can't instantiate the class. So there is nothing wrong with this code.
In a deriving class you can call the constructor and set the final property:
public class Foo extends FooType
{
public Foo()
{
super(); // <-- Call constructor of FooType
}
}
if you don't specify a call to super(), it will be inserted anyway by the compiler.
You can create concrete sub-classes of FooType and they will all have a final field called myvar.
BTW: A public constructor in an abstract class is the same as a protected one as it can only be called from a sub-class.
What is your doubt?
Ok. See, an abstract class can have a constructor. It's always there-implicit or explicit. In fact when you create an object of a subclass of an abstract class, the first thing that the constructor of the subclass does is call the constructor of its abstract superclass by using super(). It is just understood, that's why you don't have to write super() explicitly unless you use parameterized constructors. Every class even if it is abstract, has an implicit constructor which you cannot see. It is called unless you create some constructor of your own. so long you created abstract classes without creating any custom constructor in it, so you didn't know about the existence of the implicit constructor.
You definitely can declare final variable in abstract class as long as you assign value to it either in the constructor or in declaration. The example that guy gave makes no sense.
No you can't declare final variables inside an Abstract class.
Check Below example.
public abstract class AbstractEx {
final int x=10;
public abstract void AbstractEx();
}
public class newClass extends AbstractEx{
public void AbstractEx(){
System.out.println("abc");
}
}
public class declareClass{
public static void main(String[] args) {
AbstractEx obj = new newClass ();
obj.AbstractEx();
// System.out.println(x);
}
}
This code runs correct and produce output as
abc
But if we remove comment symbol of
System.out.println(x);
it will produce error.
I know abstract fields do not exist in java. I also read this question but the solutions proposed won't solve my problem. Maybe there is no solution, but it's worth asking :)
Problem
I have an abstract class that does an operation in the constructor depending on the value of one of its fields.
The problem is that the value of this field will change depending on the subclass.
How can I do so that the operation is done on the value of the field redefined by the subclass ?
If I just "override" the field in the subclass the operation is done on the value of the field in the abstract class.
I'm open to any solution that would ensure that the operation will be done during the instantiation of the subclass (ie putting the operation in a method called by each subclass in the constructor is not a valid solution, because someone might extend the abstract class and forget to call the method).
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Edit:
My subclasses are actually some tools used by my main program, so the constructor has to be public and take exactly the arguments with which they will be called:
tools[0]=new Hand(this);
tools[1]=new Pencil(this);
tools[2]=new AddObject(this);
(the subclasses are Hand, Pencil and AddObject that all extend the abstract class Tool)
That's why I don't want to change the constructor.
The solution I'm about to use is to slightly change the above code to:
tools[0]=new Hand(this);
tools[0].init();
tools[1]=new Pencil(this);
tools[1].init();
tools[2]=new AddObject(this);
tools[2].init();
and use an abstract getter to acces the field.
How about abstract getter/setter for field?
abstract class AbstractSuper {
public AbstractSuper() {
if (getFldName().equals("abc")) {
//....
}
}
abstract public void setFldName();
abstract public String getFldName();
}
class Sub extends AbstractSuper {
#Override
public void setFldName() {
///....
}
#Override
public String getFldName() {
return "def";
}
}
Also, I don't want to give the value
of the field as an argument of the
constructor.
Why not? It's the perfect solution. Make the constructor protected and offer no default constructor, and subclass implementers are forced to supply a value in their constructors - which can be public and pass a constant value to the superclass, making the parameter invisible to users of the subclasses.
public abstract class Tool{
protected int id;
protected Main main;
protected Tool(int id, Main main)
{
this.id = id;
this.main = main;
}
}
public class Pencil{
public static final int PENCIL_ID = 2;
public Pencil(Main main)
{
super(PENCIL_ID, main);
}
}
How about using the Template pattern?
public abstract class Template {
private String field;
public void Template() {
field = init();
}
abstract String init();
}
In this way, you force all subclasses to implement the init() method, which, since it being called by the constructor, will assign the field for you.
You can't do this in the constructor since the super class is going to be initialized before anything in the subclass. So accessing values that are specific to your subclass will fail in your super constructor.
Consider using a factory method to create your object. For instance:
private MyClass() { super() }
private void init() {
// do something with the field
}
public static MyClass create() {
MyClass result = new MyClass();
result.init();
return result;
}
You have an issue in this particular sample where MyClass can't be subclassed, but you could make the constructor protected. Make sure your base class has a public / protected constructor also for this code. It's just meant to illustrate you probably need two step initialization for what you want to do.
Another potential solution you could use is using a Factory class that creates all variants of this abstract class and you could pass the field into the constructor. Your Factory would be the only one that knows about the field and users of the Factory could be oblivious to it.
EDIT: Even without the factory, you could make your abstract base class require the field in the the constructor so all subclasses have to pass in a value to it when instantiated.
Also, I don't want to give the value of the field as an argument of the constructor.
Is there any solution to do that, or should I just change my design ?
Yes, I think you should change your design so that the subclass passes the value to the constructor. Since the subclass portion of your object isn't initialized until after the superclass constructor has returned, there's really no other clean way of doing it. Sure, this'd work:
class Super {
protected abstract int abstractField();
protected Super() { System.out.println("Abstract field: " + abstractField); }
}
class Sub {
protected int abstractField(){ return 1337; }
}
... since the implementation of abstractField() doesn't operate on object state. However, you can't guarantee that subclasses won't think it's a great idea to be a little more dynamic, and let abstractField() returns a non-constant value:
class Sub2 {
private int value = 5;
protected int abstractField(){ return value; }
public void setValue(int v){ value = v; }
}
class Sub3 {
private final int value;
public Sub3(int v){ value = v; }
protected int abstractField(){ return value; }
}
This does not do what you'd expect it to, since the initializers and constructors of subclasses run after those of the superclass. Both new Sub2() and new Sub3(42) would print Abstract field: 0 since the value fields haven't been initialized when abstractField() is called.
Passing the value to the constructor also has the added benefit that the field you store the value in can be final.
If the value is determined by the type of subclass, why do you need a field at all? You can have a simple abstract method which is implemented to return a different value for each subclass.
I think you need a factory (aka "virtual constructor") that can act on that parameter.
If it's hard to do in a given language, you're probably thinking about it incorrectly.
If I understand you correctly: You want the abstract class's constructor to do something depending on a field in the abstract class but which is set (hopefully) by the subclass?
If I got this wrong you can stop reading ...
But if I got it right then you are trying to do something that is impossible. The fields of a class are instantiated in lexical order (and so if you declare fields "below", or "after", the constructor then those will not be instantiated before the constructor is called). Additionally, the JVM runs through the entire superclass before doing anything with the subclass (which is why the "super()" call in a subclass's constructor needs to be the first instruction in the constructor ... because this is merely "advice" to the JVM on how to run the superclass's constructor).
So a subclass starts to instantiate only after the superclass has been fully instantiated (and the superclass's is constructor has returned).
And this is why you can't have abstract fields: An abstract field would not exist in the abstract class (but only in the subclass) and so is seriously(!) "off limits" to the super (abstract) class ... because the JVM can't bind anything references to the field (cause it doesn't exist).
Hope this helps.