So, in Java, the first line of your constructor HAS to be a call to super... be it implicitly calling super(), or explicitly calling another constructor. What I want to know is, why can't I put a try block around that?
My specific case is that I have a mock class for a test. There is no default constructor, but I want one to make the tests simpler to read. I also want to wrap the exceptions thrown from the constructor into a RuntimeException.
So, what I want to do is effectively this:
public class MyClassMock extends MyClass {
public MyClassMock() {
try {
super(0);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// Mocked methods
}
But Java complains that super isn't the first statement.
My workaround:
public class MyClassMock extends MyClass {
public static MyClassMock construct() {
try {
return new MyClassMock();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public MyClassMock() throws Exception {
super(0);
}
// Mocked methods
}
Is this the best workaround? Why doesn't Java let me do the former?
My best guess as to the "why" is that Java doesn't want to let me have a constructed object in a potentially inconsistent state... however, in doing a mock, I don't care about that. It seems I should be able to do the above... or at least I know that the above is safe for my case... or seems as though it should be anyways.
I am overriding any methods I use from the tested class, so there is no risk that I am using uninitialized variables.
Unfortunately, compilers can't work on theoretical principles, and even though you may know that it is safe in your case, if they allowed it, it would have to be safe for all cases.
In other words, the compiler isn't stopping just you, it's stopping everyone, including all those that don't know that it is unsafe and needs special handling. There are probably other reasons for this as well, as all languages usually have ways to do unsafe things if one knows how to deal with them.
In C# .NET there are similar provisions, and the only way to declare a constructor that calls a base constructor is this:
public ClassName(...) : base(...)
in doing so, the base constructor will be called before the body of the constructor, and you cannot change this order.
It's done to prevent someone from creating a new SecurityManager object from untrusted code.
public class Evil : SecurityManager {
Evil()
{
try {
super();
} catch { Throwable t }
{
}
}
}
I know this is an old question, but I liked it, and as such, I decided to give it an answer of my own. Perhaps my understanding of why this cannot be done will contribute to the discussion and to future readers of your interesting question.
Let me start with an example of failing object construction.
Let's define a class A, such that:
class A {
private String a = "A";
public A() throws Exception {
throw new Exception();
}
}
Now, let's assume we would like to create an object of type A in a try...catch block.
A a = null;
try{
a = new A();
}catch(Exception e) {
//...
}
System.out.println(a);
Evidently, the output of this code will be: null.
Why Java does not return a partially constructed version of A? After all, by the point the constructor fails, the object's name field has already been initialized, right?
Well, Java can't return a partially constructed version of A because the object was not successfully built. The object is in a inconsistent state, and it is therefore discarded by Java. Your variable A is not even initialized, it is kept as null.
Now, as you know, to fully build a new object, all its super classes must be initialized first. If one of the super classes failed to execute, what would be the final state of the object? It is impossible to determine that.
Look at this more elaborate example
class A {
private final int a;
public A() throws Exception {
a = 10;
}
}
class B extends A {
private final int b;
public B() throws Exception {
methodThatThrowsException();
b = 20;
}
}
class C extends B {
public C() throws Exception { super(); }
}
When the constructor of C is invoked, if an exception occurs while initializing B, what would be the value of the final int variable b?
As such, the object C cannot be created, it is bogus, it is trash, it is not fully initialized.
For me, this explains why your code is illegal.
I can't presume to have a deep understanding of Java internals, but it is my understanding that, when a compiler needs to instantiate a derived class, it has to first create the base (and its base before that(...)) and then slap on the extensions made in the subclass.
So it is not even the danger of uninited variables or anything like that at all. When you try to do something in the subclass' constructor before the base class' constructor, you are basically asking the compiler to extend a base object instance that doesn't exist yet.
Edit:In your case, MyClass becomes the base object, and MyClassMock is a subclass.
I don't know how Java is implemented internally, but if the constructor of the superclass throws an exception, then there isn't a instance of the class you extend. It would be impossible to call the toString() or equals() methods, for example, since they are inherited in most cases.
Java may allow a try/catch around the super() call in the constructor if 1. you override ALL methods from the superclasses, and 2. you don't use the super.XXX() clause, but that all sounds too complicated to me.
I know this question has numerous answers, but I'd like to give my little tidbit on why this wouldn't be allowed, specifically to answer why Java does not allow you to do this. So here you go...
Now, keep in mind that super() has to be called before anything else in a subclass's constructor, so, if you did use try and catch blocks around your super() call, the blocks would have to look like this:
try {
super();
...
} catch (Exception e) {
super(); //This line will throw the same error...
...
}
If super() fails in the try block, it HAS to be executed first in the catch block, so that super runs before anything in your subclass`s constructor. This leaves you with the same problem you had at the beginning: if an exception is thrown, it isn't caught. (In this case it just gets thrown again in the catch block.)
Now, the above code is in no way allowed by Java either. This code may execute half of the first super call, and then call it again, which could cause some problems with some super classes.
Now, the reason that Java doesn't let you throw an exception instead of calling super() is because the exception could be caught somewhere else, and the program would continue without calling super() on your subclass object, and possibly because the exception could take your object as a parameter and try to change the value of inherited instance variables, which would not yet have been initialized.
One way to get around it is by calling a private static function. The try-catch can then be placed in the function body.
public class Test {
public Test() {
this(Test.getObjectThatMightThrowException());
}
public Test(Object o) {
//...
}
private static final Object getObjectThatMightThrowException() {
try {
return new ObjectThatMightThrowAnException();
} catch(RuntimeException rtx) {
throw new RuntimeException("It threw an exception!!!", rtx);
}
}
}
Related
I am reviewing some code. Inside that code there a constructor for an event listener, similar to the following code:
public class MyClass implements ActionListener {
SomeOtherClass m_oc;
public MyClass(SomeOtherClass oc) {
if (null == oc) {
throw new IllegalArgumentException("oc cannot be null");
}
m_oc = oc;
m_oc.getClass();
}
#Override
public void actionPerformed(ActionEvent e) {
do_stuff();
}
private void do_stuff() {
/* some more code here, but this code never uses m_oc */
}
}
Now, my questions is: Why would who wrote this code call m_oc.getClass()?
That object (m_oc), which is an instance of SomeOtherClass is not used any where in the code apart from that location in the constructor.
No, there is no reason for doing this. The getClass method is non-virtual and has no side effect. Consequently, there is no way this statement itself has any effect. Furthermore, there is already an explicit check for null of the assigned reference, therefore this call cannot provoke a NullPointerException.
Some people like using getClass as a "fast" or "concise" null-check because of the way that the JIT treats this method. This is not longer true for modern VMs and does not expose your intention appropriately. Also, getClass has strange side-effects for C2 compilation. I would expect this to be the result of an incomplete refactoring. Maybe your version history reveals the origins of this statement.
There is no reason to call that method at all in that place. That's redundant since you are just calling and not receiving any output or that method won't affect the state of your object.
Can be removed.
I have a class that implements an interface. There's another class that implements this interface, too, and an instance of this second class backs my class's implementation.
For many of the methods specified by the interface, my class simply forwards them straight to the second class.
public class MyClass implements MyInterface
{
private OtherClass otherClassInstance; // Also implements MyInterface.
// ...
void foo() { otherClassInstance.foo(); }
void bar() { otherClassInstance.bar(); }
void baz() { otherClassInstance.baz(); }
// ...
}
Simply deriving my class from the second class would eliminate all of this, but it doesn't make sense because the two classes are unrelated to each other (besides implementing a common interface). They represent different things - it just so happens that a lot of my class's implementation copies that of the other class. In other words, my class is implemented atop the second class, but it is not itself a subset of the second class. As we know, inheritance is meant to express an "is-a" relationship, not to share implementation, so it's inappropriate in this case.
This portion of a talk by Joshua Bloch illustrates the situation well.
I know that Java doesn't have any language support for delegation. However, is there at least some way to clean up my class's implementation so it isn't so redundant?
An answer which is not really an answer to your actual question:
I'd say, live with the boilerplate. Let IDE generate it for you. Example: in Netbeans, add the private ArrayList field, set cursor to where you'd want the methods to appear, hit alt-insert, select "Generate Delegate Method...", click the methods you want to create a delegate for in the dialog opens, submit, go through the generated methods and make them do the right thing, you're done.
It is a bit ugly, but it is still preferable to starting to mess with reflection, when you are dealing with just one class, like it sounds. Your class is probably the kind of class, which you will complete and fully test, and then hopefully never touch again. Reflection creates runtime cost which does not go away. Suffering the auto-generated boilerplate in the source file is probably preferable in this case.
First way to use http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html see tutorial http://docs.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html
Second way using AOP you can create dispatcher that intercept all invocation of specific class
For both ways you need to manage methods processing using reflection API
EDITED TO SHOW IDEA
Following code taken from tutorial above just modified a little (see youListImpl.getRealArrayList() in invoke method)
public class DebugProxy implements java.lang.reflect.InvocationHandler {
private YouListImpl youListImpl;
public static Object newInstance(Object obj) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new DebugProxy(obj));
}
private DebugProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable
{
Object result;
try {
System.out.println("before method " + m.getName());
result = m.invoke(youListImpl.getRealArrayList(), args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
} finally {
System.out.println("after method " + m.getName());
}
return result;
}
}
This question already has answers here:
How to add test coverage to a private constructor?
(18 answers)
Closed 5 years ago.
If a class contains a bunch of static methods, in order to make sure no one by mistake initializes an instance of this class, I made a private constructor:
private Utils() {
}
Now .. how could this be tested, given that constructor can't be seen? Can this be test covered at all?
Using reflection, you can invoke a private constructor:
Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
However, you can make even that not possible:
private Utils() {
throw new UnsupportedOperationException();
}
By throwing an exception in the constructor, you prevent all attempts.
I would make the class itself final too, just "because":
public final class Utils {
private Utils() {
throw new UnsupportedOperationException();
}
}
Test the intent of the code .. always :)
For example: If the point of the constructor being private is to not be seen then what you need to test is this fact and nothing else.
Use the reflection API to query for the constructors and validate that they have the private attribute set.
I would do something like this:
#Test()
public void testPrivateConstructors() {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
If you want to have a proper test for the object construction, you should test the public API which allows you to get the constructed object. That's the reason the said API should exist: to build the objects properly so you should test it for that :).
#Test
public//
void privateConstructorTest() throws Exception {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
// check that all constructors are 'private':
for (final Constructor<?> constructor : constructors) {
Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
// call the private constructor:
constructors[0].setAccessible(true);
constructors[0].newInstance((Object[]) null);
}
to make sure no one by mistake initializes an instance of this class
Usually what I do, is to change the method/constructor from private to default package visibility. And I use the same package for my test class, so from the test the method/constructor is accessible, even if it is not from outside.
To enforce the policy to not instantiate the class you can:
throw UnsupportedOperationException("don't instantiate this class!") from the default empty constructor.
declare the class abstract: if it only contains static methods, you can call the static methods but not instantiate it, unless you subclass it.
or apply both 1+2, you can still subclass and run the constructor if your test shares the same package as the target class.
This should be quite "error proof"; malicious coders will always find a workaround :)
If you have a private constructor, it is called from some not-so-private method of your code. So you test that method, and your constructor is covered. There's no religious virtue in having a test per method. You are looking for function or better yet branch coverage level, and you can get that simply by exercising the constructor through the code path that uses it.
If that code path is convoluted and hard to test, perhaps you need to refactor it.
If you add an exception in the constructor such as:
private Utils() {
throw new UnsupportedOperationException();
}
The invocation of constructor.newInstance() in the test class will throw an InvocationTargetException instead of your UnsupportedOperationException, but the desired exception will be contained in the thrown one.
If you want to assert the thrown of your exception, you could throw the target of the invocation exception, once the invocation exception has been caught.
For instance, using jUnit 4 you could do this:
#Test(expected = UnsupportedOperationException.class)
public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException {
final Constructor<Utils> constructor = Utils.class.getDeclaredConstructor();
constructor.setAccessible(true);
try {
constructor.newInstance();
} catch (InvocationTargetException e) {
throw (UnsupportedOperationException) e.getTargetException();
}
}
Don't. The constructor is private. That's all you need. Java enforces its privacy.
Don't test the platform.
If the constructor ends up with an exception, is the object created exactly the same with a normal one?
class A {
static A o;
A() throws Exception {
o=this;
throw new Exception();
}
void f() { System.out.println("f(): entry."); };
static public void main(String[]args ) {
try {
A o =new A();
}
catch (Exception e) {
System.out.println("Exception: " + e);
}
A.o.f(); // Is it safe to use this object?
}
}
This compiles and runs, and the output of this program is:
Exception: java.lang.Exception
f(): entry.
If you catch the exception, the constructed object is never passed back to the caller, and the caller's result variable is not set. However, the static variable would, in theory, be set, and I can't see any reason why it would not be accessible.
Note, however, that method verification will not allow you to store this until after the super constructor is called, so this is not a "back door" into otherwise protected objects.
Since it's your object, "safe" is up to you.
[A little more detail: When the compiled version of your constructor is entered, the "raw" Java object is fully constructed -- no additional work is needed by the system to make it valid. The super constructor has not been called yet, however, and it's either up to you to explicitly make a super call or have the compiler insert the super call by default (which it will do at the start of the method if you don't have an explicit call). The "bytecode verifier" in the JVM has some very strict rules about what can happen in a constructor prior to calling the super constructor, and storing this to a static would be a definite no-no -- you'd get a VerifyError.]
A.o.f(); // Is it safe to use this object?
It is a regular java object that will respond to method calls just as any other Java object. This is not a source of undefined behavior as far as the Java language is concerned.
That doesn't mean it's safe to use. Many classes' safety depends on their ability to maintain important invariants, and unexpected exceptions thrown during construction or critical operations often mean that those invariants do not hold so they are not safe to use.
Consider what happens if you subclass A
public class S extends A {
boolean dirty;
S() throws Exception {
// Do work to maintain important security invariants.
dirty = true;
}
void foo() {
if (dirty) {
System.out.println("clean");
dirty = false;
}
System.out.println("foo");
}
public static void main(String... argv) {
try {
new S();
} catch (Exception ex) {}
// Now A.o is an instance of S, but S's constructor
// was never called.
S s = (S) A.o; // works.
s.foo(); // Never prints clean before printing foo.
}
}
We're trying to implement some sort of Chess game and we have defined an abstract class Piece with constructor:
public Piece(String name) throws EmptyStringException{
if(name.length()<=0)
throw new EmptyStringException();
pieceName = name;
}
And an extending class could look like this:
public King(boolean white) throws EmptyStringException{
super("King", white);
}
The 'problem' here is, if i want to create a new King piece i have to write:
try {
Piece king = new King(true);
} catch(EmptyStringException e){
e.printStackTrace();
}
instead of the much simpler:
Piece king = new King(true);
So even though i simply can't create an EmptyStringException, i still have to try/catch the exception.
How can i solve this so i can still throw the EmptyStringException in Piece, but don't have to try/catch every time i need to create a new chesspiece ?
Use runtime exception:
public class EmptyStringException extends RuntimeException
instead of plain Exception. You can still document your exception in method declaration, but you are not forcing client code to deal with the exception.
Make EmptyStringException extend RuntimeException. The compile won't complain about any RuntimeExceptions thrown in a method that are missing in the throws clause.
Note that you can even include the exception in the throws clause to document that you throw it. Except for documentation purposes, this has no effect.
You should only use checked exceptions (which are derived directly from java.lang.Exception) for exceptions that the caller should handle. You should not use them for things that "can happen" like:
Out of memory
Argument errors
IO exceptions (which the Java RT got wrong and now serves as a perfect "how not do it" example)
Since you cannot catch exceptions from parent constructors, I'd follow the other provided suggestions and make your exception a RuntimeException, or use the existing exception IllegalArgumentException.
If you were in a situation where you couldn't modify the base class or change the exception being thrown and factory method could work.
public class King {
private King() {
super("King");
}
public King createInstance() {
try {
new King();
} catch (EmptyStringException e) {
throw new RuntimeException("Unexpected expection thrown", e);
}
}
}
But in your case just having Piece throw a RuntimeException is a cleaner solution.
Also if Piece's constructor is only going to be called by subclasses, consider making it protected and using assert statements to detect an empty name.
Edited - Removed incorrect advice
So even though i simply can't create an EmptyStringException, i still have to try/catch the exception.
What do you mean? Your Piece constructor is declared as throws EmptyStringException. So as far as the compiler is concerned, it can throw an EmptyStringException, simply because you've told it so.
As has been said, use a RuntimeException.
But I will add that it should be IllegalArgumentException instead of your custom one. There is no need to create your own application specific exceptions when existing standard ones exist.
Java, Class-specific Exceptions vs. Standard Exceptions
I'm reluctant to use RuntimeExceptions because this short-circuits the built-in enforcement that all excetions be handled somewhere. Yes, on your King object the exception should never happen, it's an internal coding error, so a RuntimeException is arguably appropriate. But this is clearly not the case on your Piece object.
Java's annoying rule that the super() must be the first statement prevents you from trapping the error in the King constructor.
The alternative I've used in some programs has been to move all the constructor code to an ordinary function, and then have the constructor call this function. Like:
public class Piece
{
public Piece(String name) throws EmptyStringException
{
initPiece(name);
}
// Protect so outsiders must use legal constructors
protected Piece()
{
// nop
}
protected void initPiece(String name) throws EmptyStringException
{
if (name.length()==0)
throw new EmptyStringException();
pieceName=name;
}
}
public class King extends Piece
{
public King(boolean white)
{
try
{
initPiece("King");
}
catch (EmptyStringException panic)
{
throw new RuntimeException(panic.toString()); // should never happen
}
}
}
In other words, avoid the need to call super. Call something else to do the initialization. Then the special rules about super don't apply.
Another option is to create a factory method for King rather than a constructor. Say:
public class Piece
{
public Piece(String name) throws EmptyStringException
{
if (name.length()==0)
throw new EmptyStringException();
pieceName=name;
}
public Piece makeKing(boolean white)
{
try
{
return new Piece("King");
}
catch (EmptyStringException e)
{
throw new RuntimeException(e.toString()); // won't ever happen
}
}
}
If King really needs to be its own class, you could still do that above, it's the same concept.