I have an abstract class, AbstractNode, and a concrete class which extends it- Node.
I am trying to "program to an interface" by declaring objects of AbstractClass and instantiating them with new Node().
When I try to use the variables in Node after initializing them in the constructor, I get a Null Pointer. But everything works fine if I use a getter method instead. What am I missing?
public abstract class AbstractNode
{
String str;
public abstract String getStr();
}
public class Node extends AbstractNode
{
String str;
public Node()
{
str= new String();
}
public String getStr()
{
return str;
}
}
And the main method looks like this:
public static void main(String[] args)
{
AbstractNode n= new Node();
String nullStr= n.str;
String regularStr= n.getStr();
}
Now, nullStr contains a null reference, and regularStr contains a reference to n.str.
What is happening in here?
I can access other primitive type fields which do not require initialization, like int, directly without any getter methods.
You're "shadowing" the variable str. AbstractNode has a String named str, and then Node has a different String, also named str. The constructor for Node assigns an empty string to Node.str, but AbstractNode.str is still null because it's never been assigned. getStr() returns the value in Node.str because that's the "nearest" variable named str it sees. Your code in main is reading AbstractNode.str because the compiler is resolving its full name at compile time, and the declared type of the variable n is AbstractNode. Remove the duplicate String str in Node.
Now, nullStr contains a Null reference, and regularStr contains a reference to n.str. What is happening in here?
You've got two str variables - one declared in AbstractNode, and one declared in Node.
Now n is declared to be AbstractNode, so this:
String nullStr = n.str;
fetches the value of the variable declared in AbstractNode, whereas this:
String regularStr= n.getStr();
calls the method declared in Node, which returns the variable declared in Node.
Lessons you should learn:
Decide how many pieces of state an object should have, and only declare that many variables. Any time you have two variables with the same name in a class hierarchy, you should at least feel uncomfortable. If they genuinely represent different pieces of state, you should be able to find different names.
If you only have private fields, shadowing becomes mostly irrelevant, as you won't have direct access to the fields anyway.
I would suggest a fix of only declaring str in AbstractNode, ideally making it final, and making a protected constructor which accepts a value for it. You probably want to have an accessor to that in AbstractNode as well, although it's unclear. str isn't a descriptive name for the variable either - is it the value of the node? The name of the node? Who knows. My classes would be something like this:
public abstract class AbstractNode {
private final String name;
protected AbstractNode(String name) {
this.name = name;
}
public abstract String getName() {
return name;
}
// Presumably some abstract methods?
}
public final class Node extends AbstractNode {
public Node() {
super("Some default name");
}
}
The problem is that while methods are overridable, fields are not.
Because you declared the type of the variable as AbstractNode, the expression n.str references the field in AbstractNode, even though the actual type is Node. This is because fields are statically bound at compile time to the type.
Methods on the other hand are resolved at runtime, that's why you can override them: the expression n.getStr() is resolved based on the actual type of the object.
public String getStr()
{
return str;
}
and
String regularStr= n.getStr();
This function is overriden and at runtime the corresponding function in Node class is selected and hence you get appropriate results.
But when you say
String nullStr= n.str;
n variable from AbstractNode class is fetched(which is null).Note that Variables are read only and cannot be overriden,
Related
The below class doesn't have final keyword but its member variables are private and final and the class exposes no mutate/set methods. Is this class immutable or not?
public class Abc {
private final int id;
private final String name;
public Abc(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
}
The class itself is immutable, yes - if you create an instance of just Abc, no aspect of that can be changed after the instance has been created.
However, that doesn't mean that any code receiving a parameter of type Abc can assume it's immutable with all the benefits that carries... because the class isn't final. It's entirely possible for an object of a type compatible with Abc to be mutable:
public class Mutable extends Abc {
private String value;
public Mutable(int id, String name) {
super(id, name);
}
public void setValue(String value) {
this.value = value;
}
#Override public String toString() {
return value;
}
}
Now imagine you've got code which deals with an Abc:
public class AbcConsumer {
private final Abc abc;
public AbcConsumer(Abc abc) {
this.abc = abc;
}
// No need to create a defensive copy or anything like that...
// abc is immutable, right?
public Abc getAbc() {
return abc;
}
}
Here the consumer assumes it's fine to treat Abc as if it's an immutable class - but if someone creates an AbcConsumer by passing in a Mutable instance instead of "vanilla" Abc instance, it could cause problems.
That's why it's generally a good idea when you're creating an immutable type to make it final as well - that way any consumers know that if they receive a reference with that type, it's definitely immutable.
To put it another way: yes, the Abc class is immutable... but you can't assume that a reference with a compile-time type of Abc refers to an immutable object.
As presented, yes, the class is immutable.
The "final" keyword on a class declaration prevents it from being extended - it's not related to immutability (unless your variables are declared public or protected).
Edit; "not related" is a poor choice of words, please see Jon Skeet's answer below
No, it is most likely not.
A problem is terminology. What do you mean by class? If you mean this code, sure, it's immutable. But 'this code' is not something that is particularly relevant to the concept of immutability. That usually makes a lot more sense if we consider it: this type.
As in, is the type Abc immutable?
As in, given:
public void foo(Abc abc) { ... }
is it safe to assume that the received abc couldn't possibly change?
And then the answer is no. That is not safe to assume: The type Abc is mutable.
The reason is that someone could make this:
class SneakyAbc extends Abc {
private int id;
public void setId(int id) {
this.id = id;
}
public String getId() {
return id;
}
}
This is why immutable classes are virtually always made final, to fully guarantee it.
Depending on how fancy you want to paint with the brush of 'what does this term mean', if all methods of Abc are final, you can consider it immutable as well if you really want to: Whilst the class does not need to be immutable (a subclass can add a new non-final field and create getters and setters for this), all the stuff you can 'witness' from the Abc type, assuming you don't use reflection, do appear immutable.
Exactly what definition of immutable you go with would be required knowledge to delve any further.
Note that something like java.io.File has only final fields and is final, and yet, it has easily observable state that can be modified: just.. delete the file, and voila you can see it. You can pull similar stunts with an IdentityHashMap to create a faux but nevertheless very observable 'field'.
Thus, 'immutable' as a concept: Useful. As a boolean flag to bestow upon a certain type or some java source file: Not useful.
Records
Other Answers directly addressed your questions about immutability, class being marked final, and subclasses being mutable. I’ll add an alternative option to more briefly accomplish your goal of immutability: Records.
Java 16 brings the new records feature. If the main purpose of your class is to immutably and transparently carry data, define your class as a record. The compiler implicitly creates default constructor, getters, equals & hashCode, and toString.
A record is implicitly final, so no risk of a subclass becoming mutable.
Declare the properties in parentheses. By default, you need not put anything in the curly braces body of a record.
record Abc ( int id , String name ) {}
Instantiate like any other class.
Abc x = new Abc ( 42 , "Snuffleupagus" ) ;
The implicit getter methods are simply the property names. The JavaBeans-style get…/is… method naming is not used. (You could add such methods if required.)
System.out.println( x.name() ) ;
Snuffleupagus
It is mutable if its internal states can be changed after the class is created.
In your example, although there is no class final, the inside situations cannot be changed again because of final keyword. In this way, the class becomes immutable again
I want to ask about nested enums. I am working with old code and i found very strange construction that i not really good understand.
I have this enum :
public enum DbEngines {
ORACLE("oracle", "set define on", "set define off")
, POSTGRESQL("postgresql", "--TODO set define on", "--TODO set define off");
private final String dbEngine;
private String setOn;
private String setOff;
DbEngines(String dbEngine, String setOn, String setOff) {
this.dbEngine = dbEngine;
this.setOn = setOn;
this.setOff = setOff;
}
public String getSetOn() {
return setOn;
}
public String getSetOff() {
return setOff;
}
public String toString() {
return this.dbEngine;
}
}
I added private String to this enum, that are engine specific, so it is good place for me here. The problem is, that in some places in method declaration i see something like that
public someMethod(Enum<DbEngines> engine, ...)
And it worked perfectly without methods, but now, after changing, I couldn't call public getters of this enum. But if i change to :
public someMethod(DbEngines engine, ...)
it works without any problems with all public getters. Maybe someone could explain that?
Enum in Java is the base class for all enumeration types. One can think of it as similar to Object class.
Just like one can hold reference of object of any class using the reference of type Object, one can refer to an enumeration type using the reference of type Enum.
Object o = new Integer(10);
Enum e = DBEngine.ORACLE;
One cannot invoke a method present in inherited class but absent in superclass using the reference of superclass.
Similar explanation over here.
I am trying the Jacco testing and I am able to test the getStudentId from a class called Student which has:
public String getStudentId() {
return studentId;
}
When I try to test my other class named Product, I get an error - the only difference between the two is in the getX method. The getName method of Product is:
public String getName() {
return this.name;
}
and the error message says:
constructor Product in class Product cannot be applied to given types
The keyword this references the instance of the object you are currently in. Imagine having a class like this:
public class A {
private String property;
public void changeProperty(String property) {
this.property = property
}
}
Outside of the method the variable name property is not ambiguous and references the member variable of class A. But it is ambiguous inside the method changeProperty because there is also the argument named property.
How does Java resolves this conflict? If you just type property you will always reference the object with a smaller scope, so the argument of the method and not the member variable. By using this.property you can reference the member variable again.
If there is no such conflict in your object, like in your example, then you do not need the this statement and this.name is the same as name.
However as prevention of very nasty bugs one could always use this when referencing a member variable, just as good practice. Imagine you would create a method with such a name conflict in the future and forget about the member variable, whoops you easily create a bug that is hard to debug.
Some programmers even go further and do always give member variables other names than arguments, to prevent such name conflicts. For example member variables are often named:
mProperty or
_property
Note that the method this(...) references a constructor of the own object. It can be used in a constructor to pass the task to another constructor like:
public class A {
public A(String fileName) {
this(new File(fileName), true);
}
public A(File file) {
this(file, true);
}
public A(File file, boolean doSomething) {
// Code ...
}
}
Analogously there is also the keyword super which references the parent-class. For example:
public class A {
protected String property;
}
public class B extends A {
private String property;
public void foo() {
// Property of B
System.out.println(property);
// The same
System.out.println(this.property);
// Property of A
System.out.println(super.property);
}
}
This keyword can also be used to reference parent-constructor or other methods of the parent class.
So all in all it is just about resolving such name conflicts.
Now we know that, it is easy to see that the code you posted does not contain the bug.
When you use this.name you are using a attribute defined in your class, the attribute name. However, when you use only name, it could be any variable called so in your code, even the attribute. Example:
public String getName(){
String name = "Mery";
this.name = "Jacob";
return name;
}
This method return the value "Mery". If you put return this.name then you return the value "Jacob".
There's a chance you set studentID to a public variable. Anytime you are using this.whatever to return a variable from a getX function, the this. implies it's a private variable. More likely than not the studentID is public and that's why you got away with no 'this.' in front of it.
In Java if we declare primitive variable (not local) like int, float etc and do not initialize them, then they get initialized by their default values. Can we achieve something like this for reference variables? For example if I have an employee class which contains two int variables and in another class if I have created only reference of the employee class so is it possible that int variables get initialized by zero?
In Java if we declare primitive variable (not local) like int, float etc and do not initialize them, then they get initialized by their default values.
No, they don't. Fields do, both instance fields and class fields, but not variables.
Can we achieve something like this for reference variables?
Reference fields get the same behavior. The value they're initialized with is null.
For example if I have an employee class which contains two int variables and in another class if I have created only reference of the employee class so is it possible that int variables get initialized by zero?
If by "created a reference" you mean you've created an Employee instance, then any fields in that instance will be initialized to their defaults unless the Employee constructor gives them a different value.
Fields are initialized to null if they are from some "type" (other than primitive types), anyway if you provide default values in your "default" constructor for that class in particular you can override the default null values for those.
final class Employee {
private String firstName;
private String lastName;
// You can have more constructors here
public Employee() {
firstName = "Default Value for First Name";
lastName = "Default Value for Last Name";
}
// Getters, Setters
}
Only not local fields are initialized to default values when not explicitly initialized. So, something like this
public class Main {
boolean flag;
void foo(){
System.out.println(flag);
}
}
compiles and foo() method would print false, while something like this
public class Main2 {
void foo(){
boolean flag;
System.out.println(flag);
}
}
wouldn't even compile. Furthermore, default value for a reference is null.
What you can do is designing your class in such a way that, when class is initialized, a value is assigne to its instance variables, something like
public class Main {
boolean flag;
{
flag=true;
}
void foo(){
System.out.println(flag);
}
}
I am trying to learn Java by my self and i am making a game you all properly know, which is Monopoly.
I have searched for my answer but couldnt find it, so here it is.
I have a class Field with two variables fieldnumber and fieldname. My idea is to make a field with a number, so the program know where the players are (not relevant now).
The fieldname and fieldnumbershould only be readable (means not editable) after the program have created the fields and names for the fields.
I need to know how i can intialize these two variables into a contructor and make the variables to be only "getters", so they cant be changed later on.
(obs: the class Field is only a subclass, i need to use the data in the main class later on)
Im a bit confused and tried to read the book i am using, but no luck.
Declare the fields final, assign them in constructor and do not write setters.
Should the number of properties increase, you may consider using builder pattern to avoid constructor with many arguments.
class Field {
private final int fieldNumber;
private final String fieldName;
public Field(final int fieldNumber, final String fieldName) {
// you may validate the values here and throw exception in case of non-valid values
this.fieldNumber = fieldNumber;
this.fieldName = fieldName;
}
public int getFieldNumber() {
return fieldNumber;
}
public String getFieldName() {
return fieldName;
}
}
I suggest to make the two attribut as private (not accessible), initialize them when creating the instance, and you can use the getter to get their values:
class Field{
private String fieldname;
private int fieldnumber;
public Field (String fieldname, int fieldnumber)
{
this.fieldname = fieldname;
this.fieldnumber= fieldnumber;
}
public String getFieldname(){
return fieldname;
}
public int getFieldnumber(){
return fieldnumber;
}
public String toString(){
return fieldnumber+ " " +fieldname;
}
public boolean equals(Object obj){
Field field = (Field) obj;
return (fieldnumber == field.fieldnumber && fieldname.equals(field.fieldname);
}
}
A "getter" is a method that returns the value of your field.
A "setter" is a method typically taking one argument, setting the value of your field (possibly after some validation).
For good encapsulation, your instance fields should typically only be accessed within the maximum scope allowed within context (typically private fields with getters/setters, sometimes protected or package-protected fields when inheritance or more complex settings are required)
A field marked with the final non-access modifier can only be assigned once
In your case, if the fields are scoped within the instance of your class, but will never change once assigned, you can mark them final and assign them in a constructor or instance statement (no setters).
If they are not bound to an instance, but rather to the class, then you can mark them constant (static final) and assign them right away (you can then safely make them public if they are immutable - i.e. Strings or primitives)
Getter means a method that returns a value an object stores. A variable being a getter doesn't mean anything. Getters are usually used to get variables that are declared private; that is, variables that are not 'visible' from outside the class. See the example:
class Example {
private int value;
public Example(int valueToBeSet) {
this.value = valueToBeSet;
}
}
In the above example, the variable value is only visible from the class Example; any other class cannot get that variable. This is useful when you want that no other class is able to change its value. However, to get the value from the object, you use a getter:
class Example {
private int value;
public Example(int valueToBeSet) {
this.value = valueToBeSet;
}
public int getValue() {
return this.value;
}
}
Here the method getValue() is a getter. You cannot change the value, because it is private, but you can call the method getValue(), and get the value, because the method is public.
Other way to assign a variable's value, be able to get its value, but not be able to change it, is to use the final keyword:
class Example {
public final int value;
public Example(int valueToBeSet) {
this.value = valueToBeSet;
}
}
This way the variable's value can only be set once, in the constructor, and never again. However, you can still get the value from outside the class because it is public. This is often a good way to do things, however it has its downsides; namely as I explained, you cannot change the value anymore, and to get an object with a different value, you would have to create a new object altogether. This is the closest you can get to a "getter variable".