• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Paul Clapham
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Liutauras Vilda
Saloon Keepers:
  • Tim Holloway
  • Carey Brown
  • Roland Mueller
  • Piet Souris
Bartenders:

private Math constructor

 
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
"Math constructor is private", I saw this statement from several docs, but I do not find Math constructor in JDK1.3.1 API doc.
Is this constructor provide by compiler and declared private accessibility?
Any suggest is appreciated!
 
Cowgirl and Author
Posts: 1589
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Howdy!
The Math class constructor is declared private (by the programmers -- just as you would declare a method private), so that you aren't allowed to instantiate one (and everything you care about in Math is static, so you don't need to ever make your own Math instance).
It doesn't show up in the API docs, because the developers run javadoc without the -private flag, so javadoc does NOT produce documentation for things marked 'private'.
You can mark your own constructor private, to stop anyone from instantiating the class, and then if you want to create objects of that type you'll have to provide static code that in turn calls the private constructor.
Remember that a private constructor makes a class essentially final, since no other class can extend it.
The following code shows a Foop class, that compiles just fine, but the Boop class will not:
public class Foop {
// static code to call the constructor and make a Foop
private Foop() {
// now nobody can make one except code in the Foop class
}
}
class Boop extends Foop { }
You cannot extend Foop because the compiler (or you ) tries to put in a call to the Foop constructor, but you do not have access to it. The compiler will attempt to create a constructor for the Boop class like this:
class Boop extends Foop {
Boop() {
Foop(); <-- cannot compile this!
}
}
Does that help? I happen to love constructor questions
Cheers,
Kathy
 
Li Wenfeng
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It's a very cool pattern description, thanks a lot,J2EE jini girl!
 
Li Wenfeng
Greenhorn
Posts: 22
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
here is an exception: ^_^
class Base{
private Base(){}
Base(String s){}
}
class Sub extends Base{
Sub(){
super("s");
}
}
//Okay
 
Ranch Hand
Posts: 51
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
yes, in your code you have specified the constructor of Sub, when it instance it will invoke the Base(String s), not the private one. It is legal. If remove the super("s") in your Sub constructor, you will got a compiler error, because if there is no super(), this() in Sub() constructor, the java compiler
will auto call its parent class(private Base(){}) consturctor without parameter, it will fail.
 
Kathy Sierra
Cowgirl and Author
Posts: 1589
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kathy Sierra:

Remember that a private constructor makes a class essentially final, since no other class can extend it.


Howdy -- yes, I should have clarified that. When I say, "a private constructor..." I really mean, "ONLY a private constructor."
Cheers,
Kathy
Bonus Question: So why can't you reference an instance method in your call to super?
For example, you know you can *not* do the following:

public class Woo extends Roo {
int doStuff() {return 4; }
Woo() {
super(doStuff());
}
}
class Roo {
Roo(int i) { }
}
But why? What exactly is the problem?
Answering that question helps you understand a lot about object initialization and constructor chaining.
Cheers,
Kathy
 
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Can I respond? Can I ?
From JLS 8.8.5.1


An explicit constructor invocation statement in a constructor body may not refer to any instance variables or instance methods declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.


It is not safe to use an instance before the contruction of its super classes, because its instance fields are not yet initialized. The execution of the instance (variable) initializers of a class do not begin until the super() or possible this() invokations complete.
 
Ranch Hand
Posts: 223
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Jose Botella:
Can I respond? Can I ?
From JLS 8.8.5.1

It is not safe to use an instance before the contruction of its super classes, because its instance fields are not yet initialized. The execution of the instance (variable) initializers of a class do not begin until the super() or possible this() invokations complete.


Just a little remark:
The instance variables are constructed and assigned to their default values before calling super() though.
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Exactly as JLS 12.5 says


Whenever a new class instance is created, memory space is allocated for it with room for all the instance variables declared in the class type and all the instance variables declared in each superclass of the class type, including all the instance variables that may be hidden (�8.3). If there is not sufficient space available to allocate memory for the object, then creation of the class instance completes abruptly with an OutOfMemoryError. Otherwise, all the instance variables in the new object, including those declared in superclasses, are initialized to their default values (�4.5.5).

 
Shishio San
Ranch Hand
Posts: 223
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Jose Botella:
Exactly as JLS 12.5 says


So you mean it still remains unsafe though it has a default value that is implicitly intialized. ?
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes because a programmer might (incorrectly) expect that they were initialized to the values given by the initializers.
 
Shishio San
Ranch Hand
Posts: 223
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Okidokie, i got your point thx
 
Kathy Sierra
Cowgirl and Author
Posts: 1589
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
How 'bout we take it a little further...
So now we know that you can't use your instance variables (or instance methods) until *after* the super constructor completes. But why is it often a bad idea to invoke an instance method ANYWHERE in the constructor?
I was going to give a hint, but ya'all are too smart in here, so no hint
--Kathy
 
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I thought this was a problem only if the instance method is non-final and non-private.
(This may actually be the hint that Kathy decided not to post...)
[ October 26, 2002: Message edited by: Ron Newman ]
 
Jose Botella
Ranch Hand
Posts: 2120
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
An intance method invoked anywhere in the contructor could rely on instance fields that are not yet initialized, just because they are initialized after the method call.
What about placing all of such invokations at the end of the constructor?
Anyway, Ron's right; if the method was overriden the executing method could be one in the subclass that relies on instance fields of the subclass not yet initialized.
 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
Great discussion here. Going back to the original question, here is sample code with private constructors. I was able to instatiate it and get the results fine. How is that possible?
import java.io.*;
class test {
private int x;
private test() { x = 0;}
private test(int i) {x = i; }
void printX() {
System.out.println("X is " + x);
}
public static void main(String args[]) {
test t1 = new test();
test t2 = new test(10);
t1.printX();
t2.printX();
}
}
Out put was :
X is 0
X is 10
I wonder if a private constructor just prevents subclassing it. If that is true, why not use final instead. I don't clearly understand what the purpose of a private constructor is? Can anyone share their knowledge please?
 
Shishio San
Ranch Hand
Posts: 223
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi
Private members are accessible inside the class where they were declared but not outside it.
 
Mocha D'Late
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
great. thanks. i wrote a sample to test it and i see compiler errors.
 
Kathy Sierra
Cowgirl and Author
Posts: 1589
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Mocha D'Late:
I don't clearly understand what the purpose of a private constructor is? Can anyone share their knowledge please?


Howdy,
You were able to instantiate because all of your code was in the same class, and private still allows any code � static or instance � within the same class to have access.
But if you try to make an instance from a *different* class (in other words, code that you didn't necessarily write), you won't be able to compile. So private let's you control who gets to make one -- it just doesn't control *you* from your own privately-marked code. It's the whole "*you* wrote that class so we assume *you* knew what you were doing."
(Which is a big assumption for me � I write code all the time not knowing what I'm doing )
Anyway, private constructors are crucial for making Singletons (where you only want a *single* instance to be made of that class, fairly common) or where you want to have only static methods and create *no* instances at all (extremely rare, but this is how you'd do it).
Cheers,
Kathy
 
Kathy Sierra
Cowgirl and Author
Posts: 1589
5
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Jose Botella:
Anyway, Ron's right; if the method was overriden the executing method could be one in the subclass that relies on instance fields of the subclass not yet initialized.


Yep
I have had a lot of students who are amazed to learn that "polymorphism still works", even when the object is still in the process of being created.
So just to expand a tiny bit on what Jose said, if a constructor hits an instance method, we know that within *that* constructor, *that* particular object's instance variables have been initialized, so no problem. Unless... here's the scary part the instance method has been overridden by a subclass, and it is the *subclass* that is in the process of creation.
In that case, it is the not-yet-fully-formed-and-initialized subclass' instance method that runs, even though the subclass constructor has not even completed, because we are still in the superclass constructor!
So we have the same problem as the original question, the instance variables of the subclass still have only their default � as opposed to explicit � initial values, and IF that overridden instance method relies on them, Big Trouble.
Bottom line: an object can have its instance methods invoked even while the object is still in a Schroedinger's Object state.
So best not to invoke an instance method from a constructor, if that instance method could one day be overridden (hence, Ron's crafty clue
Cheers,
Kathy
 
Ron Newman
Ranch Hand
Posts: 1056
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've heard it said that this is one of the few things C++ got right and Java got wrong -- that in C++, the object is still a SuperClass (and thus not polymorphic) until the SuperClass constructor is finished running.
reply
    Bookmark Topic Watch Topic
  • New Topic