First, quick reminder: what will be result when you execute following code?
public class Loader { { System.out.println("a"); } X x; static { System.out.println("b"); } Loader() { System.out.println("c"); } { System.out.println("d"); } static class X { static { System.out.println("e"); } } public static void main(String[] args) { System.out.println("f"); new Loader(); } }
When we get into this piece of code we realized (surprisingly!) that it doesn't compile, but it is simple and fixing doesn't take a lot of time. However, what if we have following restrictions in code manipulation:
main()
method can't be changed),What can you do, to make this code able to compile without changing the result?
class Parent { } class A extends Parent { public boolean test() { return false; } } class B extends Parent { public boolean test() { return true; } } public class X { public static void main(String[] args) { A a = new A(); B b = new B(); boolean t = (true ? a : b).test(); } }
Result will be:
b – after class is loaded, static blocks are executed,
f – execution of main() method,
a, d – creation object of class Loader will execute subsequent (ordered by position in class) class initializations blocks,
c – execution of class constructor.
Letter e will not be printed because static inner class is loaded at the time of first usage. In above example this class is not created, so it will not be loaded as well. Even despite the fact, that it is attribute in class Loader
, because it is just type declaration and object is not created.
Tenary operator can't be used as it is, because compiler:
Compiler at the compile phase can't define what will be the result of the ternary operator (even though in this example, optimizer can figure out resulting type), so we have to be sure that in both cases calling method test()
will be possible.
Besides that in this example, both types have test()
method, compiler will look for common super class, so it will find Parent class, that doesn't have test()
method.
What can we do about it? If ternary operator can't be changed, it means we have to assure that Parent class has test()
method. We can do it:
Parent
class to abstract class and add abstract test()
method, but it will break possibility to call new Parent()
;test()
method to class Parent
, that will throw an exception that it is not implemented yet. It means that derived classes should overwrite this method.The best solution would be to remove ternary operator and replace it with if-else
statement. In this case modification of Parent
class will be not needed.
Source: http://www.javaexpress.pl/article/show/Express_killers_part_IV