Default constructor and inheritance
Hi all.
I have a class that represents a contact. A contact object is valid if both name and number have been specified. Otherwise I want to be notified via a dedicated exception.
This is the code:
publicclass Contact
{
private String contact[] =new String[2];
public Contact(String name, String number)throws InvalidContactException
{
setName(name);// a method to set contact[0]
setNumber(number);// a method to set contact[1]
if (isValid())// a method to check if both name and number have been specified.
{
thrownew InvalidContactException();// this class inherits from Exception.
}
}
// other class methods.
}
This is my questions:
As the the constructorpublic Contact()
wouldn't create a valid object, I have omitted it. Is it a good thing? I know that if some new class will extend Contact by inheritance, its default constructor will call the default constructor of super class (Contact), which does not provide one. This probably will cause some kind of error.
Then I thought to provide a such constructor:
public Contact()throws InvalidContactException()
{
this("","");// It asks for a not valid contact.
}
I don't feel it's a clean solution, am I following an acceptable way?
Thanks for your attention
[2263 byte] By [
__paolo__a] at [2007-10-3 3:47:03]

If a default constructor is not a good thing for your class, don't provide it. It's fine like that! Even some Java core classes does not provide default constructor.
And it will not cause errors when extending your class, it will only force the programmer to explicitly call your non-default constructor.
> If a default constructor is not a good thing for your
> class, don't provide it. It's fine like that! Even
> some Java core classes does not provide default
> constructor.
Some technologies (e.g., Hibernate) require a no-arg constructor.
If that's the case for you, make the no-arg constructor private. Hibernate will be satisfied with that, and you don't pollute your API.
%
Generally, it's not a good idea to throw execeptions from a contructor. It's better to contruct then use "setter" methods (which do throw exceptions) to set the attributes... better is a getInstance() method which returns a new Me, and can throw exceptions... contructors should be a kept simple as possible.
To prevent a class being instantiated with the default constructor then just give it a private contructor... ie: private Contact() {}
... and hibernate is a good example of a library which doesn't allow you to control what happens when it hits an exception from a contructor.
Cheers. Keith.
> Generally, it's not a good idea to throw execeptions
> from a contructor. It's better to contruct then use
> "setter" methods (which do throw exceptions) to set
> the attributes.
I disagree with this. A constructor should leave an object in a fully-initialized, ready-to-go state at all times. Constructing and calling setters flies in the face of this.
If you try to construct an object in such a way that its invariants are violated, I think it's perfectly acceptable to throw an exception. Tell the client right away if you can't continue.
> .. better is a getInstance() method
> which returns a new Me, and can throw exceptions...
That method is a constructor in every way but the name.
> contructors should be a kept simple as possible.
As should all code. But they should not be simplified to the point where they fail to initialize an object properly.
> To prevent a class being instantiated with the
> default constructor then just give it a private
> contructor... ie: private Contact() {}
You can still instantiate a class witha private default constructor. If there's another ctor that takes arguments, just call that.
> ... and hibernate is a good example of a library
> which doesn't allow you to control what happens when
> it hits an exception from a contructor.
>
> Cheers. Keith.
%
> Generally, it's not a good idea to throw execeptions
> from a contructor.
It's perfectly fine to throw exceptions from a c'tor.
> It's better to contruct then use
> "setter" methods (which do throw exceptions) to set
> the attributes... better is a getInstance() method
> which returns a new Me, and can throw exceptions...
> contructors should be a kept simple as possible.
Constructors should be fairly simple, in that their only job is to put the object into a valid state. If that means doing some things that might throw exceptons, there's nothing inherently wrong with that.
jverda at 2007-7-14 21:43:55 >

> It's perfectly fine to throw exceptions from a
> c'tor.
>
Normally when an object is created it involves three steps
allocate memory
assign reference to resource
call constructor to initialize
now since the JMM is broken the order cannot be guaranteed. When an exception is thrown in the constructor that would be the initialization part not completed, so would an object be created? If it might be then what do you think wouldn't it be better to use some kind of a factory like
createObjectMMM(arguments)
while making the constructor private where the create Object does the validation before it even calls the constructor.
> > It's perfectly fine to throw exceptions from a
> > c'tor.
> >
>
>
> Normally when an object is created it involves three
> steps
>
> allocate memory
> assign reference to resource
> call constructor to initialize
>
> now since the JMM is broken the order cannot be
> guaranteed. When an exception is thrown in the
> constructor that would be the initialization part not
> completed, so would an object be created? If it
> might be then what do you think wouldn't it be better
> to use some kind of a factory like
>
> createObjectMMM(arguments)
>
> while making the constructor private where the create
> Object does the validation before it even calls the
> constructor.
I'm not sure what your point is, especially the part about "since the JMM is broken, the order cannot be guaranteed." Can you be more specific? The JLS is quite specific on what happens and in what order when an object is created, including when an exception is thrown.
[url http://java.sun.com/docs/books/jls/third_edition/html/execution.html#12.5]JLS 12.5 Creation of New Class Instances[/url]
What downside are you claiming to throwing an exception from a c'tor?
jverda at 2007-7-14 21:43:56 >

> > > It's perfectly fine to throw exceptions from a
> > > c'tor.
> > >
> >
> >
> > Normally when an object is created it involves
> three
> > steps
> >
> > allocate memory
> > assign reference to resource
> > call constructor to initialize
> >
> > now since the JMM is broken the order cannot be
> > guaranteed. When an exception is thrown in the
> > constructor that would be the initialization part
> not
> > completed, so would an object be created? If it
> > might be then what do you think wouldn't it be
> better
> > to use some kind of a factory like
> >
> > createObjectMMM(arguments)
> >
> > while making the constructor private where the
> create
> > Object does the validation before it even calls
> the
> > constructor.
>
>
> I'm not sure what your point is, especially the part
> about "since the JMM is broken, the order cannot be
> guaranteed." Can you be more specific? The JLS is
> quite specific on what happens and in what order when
> an object is created, including when an exception is
> thrown.
>
> [url
> http://java.sun.com/docs/books/jls/third_edition/html/
> execution.html#12.5]JLS 12.5 Creation of New Class
> Instances[/url]
>
>
> What downside are you claiming to throwing an
> exception from a c'tor?
IMHO The JLS does specify the steps but doesnot mention the order. Please correct me if it specifies the order as well.
If an exception is thrown in a constructor would an object be created or not?
A a = new A();
now the constructor A() throwns and exception. My question is would a be null in that case or not? Specially considering as I mentioned the order is not guaranteed in my previous post and JMM is broken. Considering a might or might not be null , what would be the benefit of such an exception. Following the broken DCL semantics and I am sure you must have gone through article
http://www.javaworld.com/jw-02-2001/jw-0209-double.html
> > I'm not sure what your point is, especially the
> part
> > about "since the JMM is broken, the order cannot
> be
> > guaranteed." Can you be more specific? The JLS is
> > quite specific on what happens and in what order
> when
> > an object is created, including when an exception
> is
> > thrown.
> >
> > [url
> >
> http://java.sun.com/docs/books/jls/third_edition/html/
>
> > execution.html#12.5]JLS 12.5 Creation of New
> Class
> > Instances[/url]
> >
> >
> > What downside are you claiming to throwing an
> > exception from a c'tor?
>
> IMHO The JLS does specify the steps but doesnot
> mention the order. Please correct me if it specifies
> the order as well.
Read that section. The order is the order it states there.
>
> If an exception is thrown in a constructor would an
> object be created or not?
>
> A a = new A();
>
Depends what you mean by "object created." The memory is allocated. Which of the rest of the steps have been run (instance initializers, ancestor c'tors, this c'tor) depend on where the exception was thrown. Regardless, though, you won't get back a value in the variable a.
> now the constructor A() throwns and exception. My
> question is would a be null in that case or not?
a will have whatever value it had before that method, if any. But it doesn't matter, because, since an exception has been thrown, the steps after that statement are not executed.
> Specially considering as I mentioned the order is not
> guaranteed in my previous post and JMM is broken.
You have yet to provide support or clarification for this, or what it means in this context.
> Considering a might or might not be null ,
There is no "might or might not." See above.
> what
> would be the benefit of such an exception.
> Following the broken DCL semantics and I am sure
> you must have gone through article
DCL is a completely different issue.
jverda at 2007-7-14 21:43:56 >

> Regardless, though, you won't get back a value in the> variable a.if that is the case I stand corrected.
> > Regardless, though, you won't get back a value in
> the
> > variable a.
>
> if that is the case I stand corrected.
You see why, right?
When there's an assignment, the RHS is evaluated completely before anything it stuck into the LHS (as far as a single thread is concerned--previous JMMs let other threads see the results early, IIRC).
The exception occurs, execution of that statement completes abruptly, and control is transferred to the nearest enclosing catch block, if present.
Now, you might wonder about this: A a;
try {
a = new A();
}
catch (Throwable th) {}
System.out.println(a);
After all, we caught the exception, smothered it, and moved on, so what will a be?
It won't compile. "variable a might not have been set" or something to that effect.
jverda at 2007-7-14 21:43:56 >

> > Regardless, though, you won't get back a value in the
> > variable a.
>
> if that is the case I stand corrected.
Unfortunately that isn't necessarily true.
(JMM presumably means Java Memory Model.)
At least in versions prior to 1.5 it was possible although not likely that assignment could occur as follows in the VM.
temp = memory
start processing ctor
a = temp
end processing ctor
The only time this matters is if multiple threads attempt to access a.
Note that I consider the above very unlikely to happen and I doubt it would happen on a Sun VM.
If you want to protect in the above scenario you would have to do one of the following
1. Make sure multiple threads can't access it.
2. Do absolutely nothing in the constructor.
Myself if it seemed an issue to me then I would do 1 anyways and that would still make it a non-issue.