Using final methods to initialize an instance variable - java

From the Sun docs
Normally, you would put code to
initialize an instance variable in a
constructor.There are two
alternatives to using a constructor to
initialize instance variables:
initialize blocks and final methods.
I could understand the use of initialize blocks. Can anyone please explain the use of final methods for instance var initialization? A non-final public setter can do this job. Why not just use them ?

The advantage is already described in the very same Sun tutorial you linked to:
A final method cannot be overridden in a subclass. This is discussed in the lesson on interfaces and inheritance.
This is especially useful if subclasses might want to reuse the initialization method. The method is final because calling non-final methods during instance initialization can cause problems. Joshua Bloch describes this in more detail in Effective Java(item 17 Design and document for inheritance).
The reason a non-final method is dangerous in initialization is because the instance initialization of the superclass executes before the sub class is initialized. Therefore if the non-final method is overriden in the sub class and is executed during the initialization of the superclass it may be accessing uninitialized fields of the subclass giving erroneous results.
The general rule is(quoting from Effective Java): Constructors must not invoke overridable methods, directly or indirectly.

It's explained on the same page of the referenced tutorial. The reason is that a non-final method can be overriden by up subclass. Here's an example:
class Whatever {
private List<String> myVar = initializeInstanceVariable();
protected List<String> initializeInstanceVariable() {
return new ArrayList<String>();
}
}
class Whoever extends Whatever {
#Override
protected List<String> initializeInstanceVariable() {
return Collections.unmodifiableList(super.initializeInstanceVariable());
}
}
So if you create Whoever, myVar will become unmodifiable ;-)

Other examples
From alykhantejani.github.io
I made it compilable and simplified it.
Duck.java
public class Duck {
String sound = "quack";
protected String speech;
public Duck() {
initSpeech();
}
protected void initSpeech() {
speech = "sound = " + sound;
}
public void speak() {
System.out.println(speech);
}
protected String getSound() {
return sound;
}
}
SqueakyDuck
public class SqueakyDuck extends Duck {
String squeakSound = "squeak";
public SqueakyDuck() {
super();
}
#Override
protected void initSpeech() {
speech = "sound = " + squeakSound;
}
#Override
protected String getSound() {
return squeakSound;
}
}
Main.java
public class Main {
public static void main(String[] args){
Duck squeaky = new SqueakyDuck();
squeaky.speak();
System.out.println(squeaky.getSound());
}
}
Output:
sound = null
squeak
My example
Superclass.java
public class Superclass {
protected int x = m();
protected int m() {
return 8;
}
}
Subclass.java
public class Subclass extends Superclass {
private int y = 7;
#Override
protected int m() {
return y;
}
}
Main.java
public class Main {
public static void main(String[] args) {
Superclass s = new Subclass();
System.out.println(s.x);
}
}
Output:
0
Order of execution:
main
m from Subclass (y is not initialized in this moment and 0 is the default value for int)
constructor Superclass
constructor Subclass

Related

Java Inheritance and method overriding program

I have the following exercise regarding inheritance and methods overriding, and the question is why the 'System.out.println(f1)' in the 'initialize()' method in the parent class is called with param '0', and what is needed to do to for it will be called with param '6'. Please help me understand it. Thanks in advance.
public class Solution {
public static void main(String[] args) {
new B(6);
}
public static class A {
private int f1 = 7;
public A(int f1) {
this.f1 = f1;
initialize();
}
protected void initialize() {
System.out.println(f1);
}
}
public static class B extends A {
protected int f1 = 3;
public B(int f1) {
super(f1);
this.f1 += f1;
initialize();
}
protected void initialize() {
System.out.println(f1);
}
}
}
Privare methods cannot be overriden. You can write the method in child but practically it is not overriding
From the Java language specification JLS.
Note that a private method cannot be hidden or overridden in the technical sense of those terms. This means that a subclass can declare a method with the same signature as a private method in one of its superclasses, and there is no requirement that the return type or throws clause of such a method bear any relationship to those of the private method in the superclass.
Your parent method is not getting called with parameter value as 0. if you can see parent's constructor is overriding the value this.f1=f1 the value of f1 will be 6. Therefore output will be 6 and 9.

Java method with abstract class as parameter that returns instance of the child class

I'm sure this will have been asked before but I can't find it after searching for some time.
I need a function that will do something like the following:
public static AbstractClass createClass(Class<AbstractClass> theChildClass, int someVariable){
AbstractClass theInstance = theChildClass.newInstance(someVariable);
return theInstance;
}
Then on AbstractClass I want to define it like so:
public abstract class AbstractClass{
private int someVariable;
public AbstractClass(int someVariable){
this.someVariable = someVariable;
initOnChild();
}
protected abstract void initOnChild();
}
Then on the child classes I ideally don't want to define the "public ChildClass(int someVariable){}" method, so they look like this:
public class ChildClass extends AbstractClass{
#Override
protected void initOnChild(){
//do some stuff
}
}
The ideal outcome I'm after is being able to call the method like so:
ChildClass theInstance = UtilityClass.createClass(ChildClass.class, 1);
Is this even possible? Any solutions or advice much appreciated.
No. Constructors are not inherited (and therefore are not members in JLS-speak). Depending on the situation you may want to apply the strategy pattern, say.
(ObNote: Generally it's considered a bad idea to call overrideable methods from constructors, and reflection is almost always a really bad idea.)
No, but there is a solution.
First the problem with calling an overriden method in the constructor:
abstract class A {
A() {
init();
}
protected abstract void init();
}
class B extends A {
public String x = null;
public String y;
#Override
protected void init() {
x = "x";
y = "y";
}
}
public static void main(String[] args) {
B b = new B();
System.out.printf("x=%s, y=%s%n", b.x, b.y);
}
Would of course give:
x=null, y=y
in B() - all fields zeroed
super() called, A()
in A() B.init() called
in B() field initialisations are done
But it is not obvious from reading superficially, and when using fields in the base class, can become less obvious.
Now the solution.
As you have a static factory method, maybe place this method in AbstractClass. Then it can call init after construction.
public static <T extends AbstractClass> T create(Class<T> childClass, int param) {
T instance = childClass.getConstructor().newInstance();
instance.init(param);
return instance;
}
This executes the default constructor.
Should this still be unsatisfactory, then it just might be that some datastructure does not reside in the correct inheritance level, or should be restructured.

How to initialize a protected final variable in a child class of an abstract parent in Java?

I tried this:
class protectedfinal
{
static abstract class A
{
protected final Object a;
}
static class B extends A
{
{ a = new Integer(42); }
}
public static void main (String[] args)
{
B b = new B();
}
}
But I got this error:
protectedfinal.java:12: error: cannot assign a value to final variable a
{ a = new Integer(42); }
^
1 error
How to work around this problem?
Some people suggested here to use a constructor but this works only in some cases. It works for most objects but it is not possible to reference the object itself from within the constructor.
static abstract class X
{
protected final Object x;
X (Object x) { this.x = x; }
}
static class Y extends X
{
Y () { super (new Integer(42)); }
}
static class Z extends X
{
Z () { super (this); }
}
This is the error:
protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
Z () { super (this); }
^
One could argue that it does not make much sense to store this kind of reference, because this exists already. That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable.
static class Z extends X
{
Z () { super (new Any (this)); }
}
So how can I write an abstract class, which forces all child classes to have a final member which gets initialized in the child?
You have to initialize A.a in its constructor. Subclasses will use super() to pass initializer to A.a.
class protectedfinal {
static abstract class A {
protected final Object a;
protected A(Object a) {
this.a = a;
}
}
static class B extends A {
B() {
super(new Integer(42));
}
}
public static void main (String[] args) {
B b = new B();
}
}
You cannot use this until superclass constructors were called, because at this stage the object is not initialized, even Object constructor hasn't run at this point, therefore calling any instance methods would lead to unpredictable results.
In your case, you have to resolve circular reference with Z class in another way:
Z () { super (new Any (this)); }
Either use a non-final field or change class hierarchy. Your workaround with instance method super(new Any(a())); would not work for the same reason: you cannot call instance methods until superclass constructors were run.
In my personal oppinion, your problems hints towards a flaw in design.
But to answer your question. If absolutly necessary, you can change final fields in java using reflection.
And if everything fails, you can still utilize sun.misc.unsafe.
But I strongly discourage you from doing so, since it potentially kills your vm.
My work around so far is to use methods instead of final members:
class protectedfinal
{
static abstract class AA
{
protected abstract Object a();
}
static class BB extends AA
{
#Override
protected Object a() { return this; }
}
public static void main (String[] args)
{
AA a = new BB();
System.out.println (a.a());
}
}
But I would like to use final members, because I think accessing a final member is faster than calling a method. Is there any chance to implement it with final members?

get caller class name from inherited static method

I have following classes (note that methods are static):
class Base
{
public static void whosYourDaddy()
{
Class callerClass = // what should I write here to get caller class?
System.out.print(callerClass.getName());
}
}
Class A extends Base
{
public static void foo()
{
A.whosYourDaddy();
}
}
Class B extends Base
{
public static void bar()
{
B.whosYourDaddy();
}
}
And when I call:
A.foo();
B.bar();
I'd like to get output:
AB instead of BaseBase. Is it even possible with static methods (in Java 7)?
What you can do, but shouldn't :) is use the Throwable getStackTrace method. Aside from the smell, this is pretty slow, because getting the stack trace isn't that fast. But you will get an array of StackTraceElement, and each one will contain the class of teh class that is calling it (and you can also get the file and line, and if you separate the two with a : you can get a clickable link in eclipse, not that I'd ever do such a thing...).
Something like
String className = new Throwable().getStackTrace()[1].getClassName();
Hope that helps :)
private static class Reflection {
private static final SecurityManager INSTANCE = new SecurityManager();
static Class getCallClass() {
return INSTANCE.getCallClass(2);
}
private Reflection() {
}
private static class SecurityManager extends java.lang.SecurityManager {
public Class getCallClass(int i) {
Class[] classContext = getClassContext();
if (i >= 0 && i + 1 < classContext.length) {
return classContext[i + 1];
}
return null;
}
};
}
Is it even possible with static methods (in Java 7)?
No, Static methods aren't inherited. Only non-static methods are inherited.
In your case change Base (and subclasses) as follows:
class Base
{
public void whosYourDaddy()
{
Class<?> callerClass = getClass();
System.out.print(callerClass.getName());
}
}

Java Access Abstract Instance variables

I have an abstract class with a variable like follows:
public abstract class MyAbstractClass {
int myVariable = 1;
protected abstract void FunctionThatUsesMyVariable();
}
Then when I go to instantiate my class through the following code, myVariable cannot be seen:
MyAbstractClass myClass = new MyAbstractClass() {
#Override
protected void FunctionThatUsesMyVariable() {
// TODO Auto-generated method stub
}
};
What am I doing wrong and how can I achieve what I am trying to achieve?
You are declaring myVariable as having package access and your 2 classes reside in different packages. Thus the variable is not visible to inheriting classes. You can declare it with protected access to be visible or put the 2 classes in the same package.
public abstract class MyAbstractClass {
protected int myVariable = 1;
protected abstract void FunctionThatUsesMyVariable();
}
Seems to work for me:
public class Test {
public static abstract class MyAbstractClass {
int myVariable = 1;
protected abstract void FunctionThatUsesMyVariable();
}
public void test() {
MyAbstractClass myClass = new MyAbstractClass() {
#Override
protected void FunctionThatUsesMyVariable() {
myVariable = 2;
}
};
}
public static void main(String args[]) {
new Test().test();
}
}
I suspect you are declaring the two classes in different packages. If that is what you want then you should make the variable protected (or public if you must). Alternatively - obviously - put them in the same package.
Because you're still subclassing/extending the abstract class and unless you make it protected, the field isn't inherited.
Declare your variable as protected. It's package-private by default.

Categories