Need to initialize a static final field in the subclasses - java

I asked a question, but it was very dirty, and a lot of people didn't understand. So, I need to declare a final static field, that is only going to be initialized in the subclasses. I'll show an example:
public class Job {
public static final String NAME;
}
public class Medic extends Job {
static {
NAME = "Medic";
}
}
public class Gardener extends Job {
static {
NAME = "Gardener";
}
}
Something like this. I know this code is not going to work, since the NAME field in the Job class needs to be initialized. What i want to do is to initialize that field individually in each subclass (Medic, Gardener).

You need this
public enum Job {
MEDIC(0),
GARDENER(1);
/**
* get identifier value of this enum
*/
private final byte value;
private Job(byte value) {
this.value = value;
}
/**
* get identifier value of this enum
* #return <i>int</i>
*/
public int getValue() {
return this.value;
}
/**
* get enum which have value equals input string value
* #param value <i>String</i>
* #return <i>Job</i>
*/
public static Job getEnum(String value) {
try {
byte b = Byte.parseByte(value);
for (Job c : Job.values()) {
if (c.getValue() == b) {
return c;
}
}
throw new Exception("Job does not exists!");
} catch (NumberFormatException nfEx) {
throw new Exception("Job does not exists!");
}
}
/**
* get name of this job
*/
public String getName() {
switch (this) {
case MEDIC:
return "Medic";
case GARDENER:
return "Gardener";
default:
throw new NotSupportedException();
}
}
}

Why not declare an abstract method in the base class?
public abstract class Job {
public abstract String getJobName();
}
Then you can return individual names in each implementation:
public class Medic extends Job {
#Override
public String getJobName() {
return "Medic";
}
}
public class Gardener extends Job {
#Override
public String getJobName() {
return "Gardener";
}
}
It does not make a lot of sense to have a final static field.

You cannot do this. The static field has the only once instance per class where it's declared. As both Medic and Gardener share the same Job superclass, they also share the same NAME static field. Thus you cannot assign it twice.
You cannot assign it even once in subclass as it's possible that Job class is already loaded and initialized, but no subclasses are loaded yet. However after class initialization all the static final fields are required to be initialized.

Related

How to initialize a value when creating an object in a static block

When creating the Racing class in ApplicationTest, I want to hand over the FixNumberBehavior class to the argument.
As shown below, to pass the argument to initialize FixNumberBehavior, but cannot pass the class field value to the static block.
The error message is as follows.
Variable 'isMove' might not have been initialized
FixNumberBehavior.java
public class FixNumberBehavior implements CarMoveBehavior {
private final boolean isMove;
private static FixNumberBehavior fixNumberBehavior;
static {
fixNumberBehavior = new FixNumberBehavior(); //error
}
public FixNumberBehavior(final boolean isMove) {
this.isMove = isMove;
}
#Override
public boolean moveBehavior() {
return isMove;
}
}
Racing.java
public class Racing {
private List<Car> cars;
private CarMoveBehavior carMoveBehavior;
public Racing(List<Car> cars, final CarMoveBehavior carMoveBehavior) {
this.cars = cars;
this.carMoveBehavior = carMoveBehavior;
}
public List<Car> getCars() {
return cars;
}
public void drive() {
cars.stream()
.forEach(car -> racingCondition(car));
}
private void racingCondition(Car car) {
if (carMoveBehavior.moveBehavior()) {
car.moveForward();
}
}
}
ApplicationTest
#ParameterizedTest
#CsvSource({"a,aa,aaa"})
void fixRandomNumberTest(String one, String two, String three) {
final List<Car> cars = Arrays.asList(new Car(one), new Car(two), new Car(three));
Racing racing = new Racing(cars, new FixNumberBehavior(true));
racing.drive();
racing.drive();
assertAll(
() -> assertThat(cars.get(0).getStep()).isEqualTo(2),
() -> assertThat(cars.get(1).getStep()).isEqualTo(2),
() -> assertThat(cars.get(2).getStep()).isEqualTo(2)
);
}
How can I initialize an object in the static block?
The problem is FixNumberBehavior has a final field that must be set in the constructor, or in an assignment on the field definition line.
While there is a constructor that takes a value for that field, the static block is not using that constructor, but instead a no-arg constructor.
Pass the value for that final field (isMove) in the new statement.
I am not sure why you want to overcomplicate things by
providing no-argument constructor when you already have constructor in which you let client decide if created instance of FixNumberBehavior will set isMove to true or false.
changing (in your answer) isMove from being final to being static. Those two keywords have different purpose:
final prevents reassigning new value to it
static makes this field a class field, not instance field, so even if you create two instances of FixNumberBehavior there will be only one isMove variable which they both will use (so you can't preserve in one instance state like isMove=true and in other state isMove=false).
What you are looking for is probably simply
public class FixNumberBehavior implements CarMoveBehavior {
private final boolean isMove;
private static FixNumberBehavior fixNumberBehavior = new FixNumberBehavior(true);
//set value you want here ^^^^
public FixNumberBehavior(final boolean isMove) {
this.isMove = isMove;
}
#Override
public boolean moveBehavior() {
return isMove;
}
}
I solved it by attaching static to the field.
Objects created in the static block are not identified when compiling. Therefore, the argument value to be transferred to the object you create in the static block must also be processed statistically.
package racingcar.model.domain;
public class FixNumberBehavior implements CarMoveBehavior {
private static boolean isMove;
private static FixNumberBehavior fixNumberBehavior;
static {
fixNumberBehavior = new FixNumberBehavior(isMove);
}
private FixNumberBehavior() {
}
public static FixNumberBehavior getInstance(){
return fixNumberBehavior;
}
public FixNumberBehavior(final boolean isMove) {
this.isMove = isMove;
}
#Override
public boolean moveBehavior() {
return isMove;
}
}

How to read and write to variables of an abstract class

Put simply, I have an abstract class containing several variables and methods. Other classes extend this abstract class, yet when I try to read the private variable in the abstract class by calling getter methods inside the abstract class, it returns null as the value of the variable.
public class JavaApplication {
public static void main(String[] args) {
NewClass1 n1 = new NewClass1();
NewClass2 n2 = new NewClass2();
n1.setVar("hello");
n2.print();
}
}
public class NewClass1 {
public String firstWord;
public void setVar(String var) {
firstWord = var;
}
public String getVar () {
return firstWord;
}
}
public class NewClass2 extends NewClass1{
public void print() {
System.out.println(makeCall());
}
public String makeCall() {
return getVar();
}
}
Still prints out null.
Until the String is initialized, it will be null. You should probably have a constructor in the abstract class to set it.
public abstract class Command
{
String firstWord; // = null
protected Command(){}
protected Command( String w )
{
firstWord = w;
}
//...
}
public class Open extends Command
{
public Open()
{
this( "your text" );
}
public Open( String w )
{
super( w );
}
// ...
}
If you need to modify the firstWord string everytime execute() is called then it may not be necessary to use a constructor with a String parameter (I added a default constructor above). However, if you do it this way then either
You must make sure setFirstWord() is called before getFirstWord(), or,
Handle the case when getFirstWord() returns null. This could be by simply using a default value (maybe determined by each subclass) or something else, like failing to execute.
As I do not know all the details of your implementation I cannot tell you further information.

Anonymous inner classes in Java

Got some incomprehensible exercise in my book.
"Create a class with a non-default constructor (one with arguments) and no default constructor (no "no-arg" constructor). Create a second class that has a method that returns a reference to an object of the first class. Create the object that you return by making an anonymous inner class that inherits from the first class."
Can anyone come out with a source code?
Edit:
I don't understand what the final source code should look like. And I came with this one:
class FirstClass
{
void FirstClass( String str )
{
print( "NonDefaultConstructorClass.constructor(\"" + str + "\")" );
}
}
class SecondClass
{
FirstClass method( String str )
{
return new FirstClass( )
{
{
print( "InnerAnonymousClass.constructor();" );
}
};
}
}
public class task_7
{
public static void main( String[] args )
{
SecondClass scInstance = new SecondClass( );
FirstClass fcinstance = scInstance.method( "Ta ta ta" );
}
}
Honestly, the exercise is quite concise unless you do not know or understand the definition of an inner class. You can find an example of an anonymous inner class here:
http://c2.com/cgi/wiki?AnonymousInnerClass
Otherwise, this concise example illustrates the problem:
/** Class with a non-default constructor and no-default constructor. */
public class A {
private int value;
/** No-arg constructor */
public A() {
this.value = 0;
}
/** Non-default constructor */
public A(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
/** Class that has a method that returns a reference to A using an anonymous inner class that inherits from A. */
public class B {
public B() { ; }
/** Returns reference of class A using anonymous inner class inheriting from A */
public A getReference() {
return new A(5) {
public int getValue() {
return super.getValue() * 2;
}
};
}
}

Accessing private field in Java class from another class

Hi all someone can explain why the last line at this code is legal:
public class HashCodeTest {
private String value = null;
HashCodeTest(String value) {
this.value = value;
}
public static void main(String[] args) {
Map<HashCodeTest, String> aMap = new HashMap<HashCodeTest, String>();
aMap.put(new HashCodeTest("test"), "test");
aMap.put(new HashCodeTest("test"), "test");
System.out.println(aMap.size());
}
#Override
public int hashCode() {
int result = 17;
return 31 * result + value.hashCode();
}
public boolean equals(HashCodeTest test) {
if (this == test) {
return true;
}
if (!(test instanceof HashCodeTest)) {
return false;
}
return test.value.equals(value);
}
}
At the last line there is access to private field of test class but this is illegal.
Thanks,
Maxim
Private fields are accessible by all instances of this class.
Because it is an instance of the same class you are using it in.
value is not a private variable of another class; it is a private variable of another instance of the same class. Therefore the access is completely legal.
Access modifiers define access for a type, not the instance of a type.

Don’t call subclass methods from a superclass constructor

Consider the following code
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package example0;
/**
*
* #author yccheok
*/
public class Main {
static class A {
private final String var;
public A() {
var = getVar();
// Null Pointer Exception.
System.out.println("var string length is " + var.length());
}
public String getVar() {
return "String from A";
}
}
static class B extends A {
private final String bString;
// Before B ever constructed, A constructor will be called.
// A is invoking a overriden getVar, which is trying to return
// an initialized bString.
public B() {
bString = "String from B";
}
#Override
public String getVar() {
return bString;
}
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
B b = new B();
}
}
Currently, in my mind, there are two ways to avoid such problem.
Either making class A final class.
static final class A {
private final String var;
public A() {
var = getVar();
// Null Pointer Exception.
System.out.println("var string length is " + var.length());
}
public String getVar() {
return "String from A";
}
}
Or
Making getVar method final
static class A {
private final String var;
public A() {
var = getVar();
// Null Pointer Exception.
System.out.println("var string length is " + var.length());
}
public final String getVar() {
return "String from A";
}
}
The author trying to suggest ways to prevent the above problem. However, the solution seems cumbersome as there are some rules to be followed.
http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/
Beside making final and the author suggested way, is there more ways to prevent the above problem (Don’t call subclass methods from a superclass constructor) from happen?
Making getVar method final
This is definitely what you need to do.
If you're relaying on the functionality of a method to initialize an object, you shouldn't let subclasses broke that method.
Answering your question, other way to prevent it is to make getVar private in A.
See this simplified version of your code:
// A.java
class A {
private final String var;
public A(){
var = getVar();
var.length();
}
private String getVar(){
return "This is the value";
}
}
class B extends A {
private final String other;
public B(){
other = "Other string";
}
public String getVar(){
return other;
}
}
class Main{
public static void main( String [] args ) {
new B();
}
}
BTW, why did you put those as static nested classes, just to create confusion?

Categories

Resources