I have a java program where a paramaterized constructor is used with the parameters names same as that of instance variables.
In such case we need to use this keyword. But when I do not use this keyword it does not gives any error instead it initializes instance variables with default values.
class Demo{
int a;
Demo(int a)
{
a = a;
}
public static void main(String args[])
{
Demo d = new Demo(5);
}
}
But when this program is executed the value of a becomes 0. How?
There's no ambiguity - in a = a;, both a's unambiguously refer to the parameter, because that is the "innermost" variable called a.
Because it is perfectly valid to assign the same value to same variable. So a = a is perfectly valid code.
But what you want to achieve is to assign value of a (method variable) to this.a (instance variable). So you need to use this keyword to refer to instance variable.
Demo(int a) {
this.a = a;
}
If you do not want to use this keyword then you need to rename method variable like
Demo(int b) {
a = b; // a will refer to instance variable in this case.
}
my question was how a's value become zero.
Refer : Primitive Data Types
Primitive datatype variable are initialized with default value. And for int 0 is default value.
You overwrite the local variable a in your code instead assigning it's value to the class variable. And the class variable is initialised with zero.
Do
Demo(int a) {
this.a = a;
}
Related
Non-static final variables can be assigned a value only once.
But why this assignment can happen only either within a declaration or in the constructor?
A final variable is defined to be immutable i.e., the value assigned to it will be the one and only for that variable x. As one can read from the JLS(§4.12.4.)
A variable can be declared final. A final variable may only be
assigned to once.
Now the constructor is just like any other method, except that it is the one that gets executed first when an object (non-static) is created from the class.
Hence, final variables can be assigned through constructors.
For example take the following code:
public class Test {
public final int x;
public Test(int x) {
this.x = x;
}
}
Compiler accepts this invocation because it is guaranteed that for that particular object its class's constructor gets invoked first and doesn't invoked again (i.e. constructor gets invoked one and only one time during the entire lifetime of object.)
However following code throws error: Non-static field 'x' cannot be referenced from a static context
public class Test {
public final int x;
static {
x = 5;
}
public Test(int x) {
this.x = x;
}
}
Since x is not a static field, it cannot be initiated within a static block.
This code would also throw error: Cannot assign a value to final variable 'x'
public class Test {
public final int x;
public Test(int x) {
this.x = x;
}
public void setX(int x) {
this.x = x;
}
}
That is because it is not guaranteed for this object, that the method setX would run first and only once. The programmer could call this method multiple times. Hence, the compiler throws an error.
So there is no way to make a variable "initializable" only once (e.g.,
a setter would block if variable was already assigned before) solely
with java syntax? I thought final might work this way but now I see
it's not.
For your question, you could simply make a variable private and add the condition to the setter method to add value only if variable is null.
For example:
public class Test {
private Integer x;
public Test() {
}
public Test(int x) {
this.x = x;
}
public void setX(int x) {
if (null == this.x) this.x = x;
}
public static void main(String[] args) {
Test y = new Test(5);
System.out.println(y.x);
y.setX(20);
System.out.println(y.x);
}
}
This is not thread safe by the way. I just added a simple example.
What does the keyword final mean in Java?
When used in a class declaration, it means that the class cannot be extended.
When used in a method, it means that the method cannot be overridden.
When used in a method parameter, it means the value of such parameter cannot be changed inside the method. (local constant)
When used in a class field ("variable), it means that it is a global constant.
Values for constants must be resolved at compile time. And, as the word implies, constants fields cannot change value. Therefore, the compiler does not allow the value to be set from a setter (mutator) method.
Contrary to what many believe, for a field to be constant, it does not have to be declared static and final. That said, since the value of a constant cannot be changed, each class instance will share the same value. Therefore, explicitly making them static reenforces this notion.
There is a fifth use of the keyword final and this is when used when local variables are declared. This is a more lengthy explanation.
What happens when you compile code?
I updated my answer because I think part of the problem is that some developers don't quite understand what happens when the code is compiled. As I mentioned before, constant values are resolved at COMPILE TIME. To understand this concept, consider the following example:
public class MyClass {
private final double PI = 3.14159;
// rest of class left out intentionally
}
If I compile this class on my laptop and then I deploy the code to some remote server, how does the server know that the global constant field PI has an assigned value of 3.14159? This is because when I compile this code, this value gets packaged with the byte code. The class constructor doesn't come into play at all in this case. HOWEVER, if the constant field is initialized to its DEFAULT value, then permanent (constant) value may be assigned via the constructor
public class MyClass {
private final double PI; // default value of 0.0
public MyClass(double value) {
PI = value;
}
// rest of code omitted intentionally
}
Here's where declaring a constant as static makes a difference. If a constant is also static, you can't do the above because calling a constructor implies that you can have multiple instances of MyClass and each instance could set a different value. This is clearly a violation of what a static member is. So, if you MUST declare a field as both static and final, understand that you cannot assign a value using this second approach. Only the first one I showed is allowed.
Final Stop's a Variable’s Reassignment
a short simple answer:
Use the keyword final when you want the compiler to prevent a variable from being re-assigned to a different object.
Whether the variable is a static variable, member variable, local variable, or argument/parameter variable, the effect is entirely the same.
Hope this helps friend =)
#StaySafe
I'm trying something like this:
class ms {
ms(int[] a) {
!! int[] a=new int[a.length];
this.a=a;
}
}
The IDE shows a.can't be resolved(in line ##), and duplicate local variable (in line !!). How to fix this? Basically I want the instance variable of class ms to have the same name as the parameter passed in the constructor.
Thanks
I think this is what you want:
class ms {
int[] a;
ms(int[] a) {
this.a = a;
}
}
Your method has a variable declared in its parameters:
int[] a
And you're trying to declare another identical variable:
int[] a
Why? You don't need to re-declare something that you already have. Your class-level variable can have the same name as your local variable, but you can't have two local variables with the same name.
Just remove the duplicate local variable:
ms(int[] a) {
this.a = a;
}
Based on my reference, primitive types have default values and Objects are null. I tested a piece of code.
public class Main {
public static void main(String[] args) {
int a;
System.out.println(a);
}
}
The line System.out.println(a); will be an error pointing at the variable a that says variable a might not have been initialized whereas in the given reference, integer will have 0 as a default value. However, with the given code below, it will actually print 0.
public class Main {
static int a;
public static void main(String[] args) {
System.out.println(a);
}
}
What could possibly go wrong with the first code? Do class variables behave different from local variables?
In the first code sample, a is a main method local variable. Method local variables need to be initialized before using them.
In the second code sample, a is class member variable, hence it will be initialized to the default value.
Read your reference more carefully:
Default Values
It's not always necessary to assign a value when a field is declared.
Fields that are declared but not initialized will be set to a
reasonable default by the compiler. Generally speaking, this default
will be zero or null, depending on the data type. Relying on such
default values, however, is generally considered bad programming
style.
The following chart summarizes the default values for the above data
types.
. . .
Local variables are slightly different; the compiler never assigns a
default value to an uninitialized local variable. If you cannot
initialize your local variable where it is declared, make sure to
assign it a value before you attempt to use it. Accessing an
uninitialized local variable will result in a compile-time error.
These are the main factors involved:
member variable (default OK)
static variable (default OK)
final member variable (not initialized, must set on constructor)
final static variable (not initialized, must set on a static block {})
local variable (not initialized)
Note 1: you must initialize final member variables on every implemented constructor!
Note 2: you must initialize final member variables inside the block of the constructor itself, not calling another method that initializes them. For instance, this is not valid:
private final int memberVar;
public Foo() {
// Invalid initialization of a final member
init();
}
private void init() {
memberVar = 10;
}
Note 3: arrays are Objects in Java, even if they store primitives.
Note 4: when you initialize an array, all of its items are set to default, independently of being a member or a local array.
I am attaching a code example, presenting the aforementioned cases:
public class Foo {
// Static and member variables are initialized to default values
// Primitives
private int a; // Default 0
private static int b; // Default 0
// Objects
private Object c; // Default NULL
private static Object d; // Default NULL
// Arrays (note: they are objects too, even if they store primitives)
private int[] e; // Default NULL
private static int[] f; // Default NULL
// What if declared as final?
// Primitives
private final int g; // Not initialized. MUST set in the constructor
private final static int h; // Not initialized. MUST set in a static {}
// Objects
private final Object i; // Not initialized. MUST set in constructor
private final static Object j; // Not initialized. MUST set in a static {}
// Arrays
private final int[] k; // Not initialized. MUST set in constructor
private final static int[] l; // Not initialized. MUST set in a static {}
// Initialize final statics
static {
h = 5;
j = new Object();
l = new int[5]; // Elements of l are initialized to 0
}
// Initialize final member variables
public Foo() {
g = 10;
i = new Object();
k = new int[10]; // Elements of k are initialized to 0
}
// A second example constructor
// You have to initialize final member variables to every constructor!
public Foo(boolean aBoolean) {
g = 15;
i = new Object();
k = new int[15]; // Elements of k are initialized to 0
}
public static void main(String[] args) {
// Local variables are not initialized
int m; // Not initialized
Object n; // Not initialized
int[] o; // Not initialized
// We must initialize them before use
m = 20;
n = new Object();
o = new int[20]; // Elements of o are initialized to 0
}
}
There are a few things to keep in mind while declaring primitive type values.
They are:
Values declared inside a method will not be assigned a default value.
Values declared as instance variables or a static variable will have default values assigned which is 0.
So in your code:
public class Main {
int instanceVariable;
static int staticVariable;
public static void main(String[] args) {
Main mainInstance = new Main()
int localVariable;
int localVariableTwo = 2;
System.out.println(mainInstance.instanceVariable);
System.out.println(staticVariable);
// System.out.println(localVariable); // Will throw a compilation error
System.out.println(localVariableTwo);
}
}
Yes, an instance variable will be initialized to a default value. For a local variable, you need to initialize before use:
public class Main {
int instaceVariable; // An instance variable will be initialized to the default value
public static void main(String[] args) {
int localVariable = 0; // A local variable needs to be initialized before use
}
}
Local variables do not get default values. Their initial values are undefined without assigning values by some means. Before you can use local variables they must be initialized.
There is a big difference when you declare a variable at class level (as a member, i.e., as a field) and at the method level.
If you declare a field at the class level they get default values according to their type. If you declare a variable at the method level or as a block (means any code inside {}) do not get any values and remain undefined until somehow they get some starting values, i.e., some values assigned to them.
All member variables have to load into the heap, so they have to be initialized with default values when an instance of class is created.
In case of local variables, they don't get loaded into the heap. They are stored on the stack until they are being used. This is before Java 7, so we need to explicitly initialize them.
In Java, the default initialization is applicable for only instance variable of class member.
It isn't applicable for local variables.
In the first case you are declaring "int a" as a local variable(as declared inside a method) and local varible do not get default value.
But instance variable are given default value both for static and non-static.
Default value for instance variable:
int = 0
float,double = 0.0
reference variable = null
char = 0 (space character)
boolean = false
I wrote following function to return a default representation 0 or false of a primitive or Number:
/**
* Retrieves the default value 0 / false for any primitive representative or
* {#link Number} type.
*
* #param type
*
* #return
*/
#SuppressWarnings("unchecked")
public static <T> T getDefault(final Class<T> type)
{
if (type.equals(Long.class) || type.equals(Long.TYPE))
return (T) new Long(0);
else if (type.equals(Integer.class) || type.equals(Integer.TYPE))
return (T) new Integer(0);
else if (type.equals(Double.class) || type.equals(Double.TYPE))
return (T) new Double(0);
else if (type.equals(Float.class) || type.equals(Float.TYPE))
return (T) new Float(0);
else if (type.equals(Short.class) || type.equals(Short.TYPE))
return (T) new Short((short) 0);
else if (type.equals(Byte.class) || type.equals(Byte.TYPE))
return (T) new Byte((byte) 0);
else if (type.equals(Character.class) || type.equals(Character.TYPE))
return (T) new Character((char) 0);
else if (type.equals(Boolean.class) || type.equals(Boolean.TYPE))
return (T) new Boolean(false);
else if (type.equals(BigDecimal.class))
return (T) BigDecimal.ZERO;
else if (type.equals(BigInteger.class))
return (T) BigInteger.ZERO;
else if (type.equals(AtomicInteger.class))
return (T) new AtomicInteger();
else if (type.equals(AtomicLong.class))
return (T) new AtomicLong();
else if (type.equals(DoubleAdder.class))
return (T) new DoubleAdder();
else
return null;
}
I use it in hibernate ORM projection queries when the underlying SQL query returns null instead of 0.
/**
* Retrieves the unique result or zero, <code>false</code> if it is
* <code>null</code> and represents a number
*
* #param criteria
*
* #return zero if result is <code>null</code>
*/
public static <T> T getUniqueResultDefault(final Class<T> type, final Criteria criteria)
{
final T result = (T) criteria.uniqueResult();
if (result != null)
return result;
else
return Utils.getDefault(type);
}
One of the many unnecessary complex things about Java making it unintuitive to use. Why instance variables are initialized with default 0 but local are not is not logical. Similar why enums dont have built in flag support and many more options. Java lambda is a nightmare compared to C# and not allowing class extension methods is also a big problem.
Java ecosystem comes up with excuses why its not possible but me as the user / developer i dont care about their excuses. I want easy approach and if they dont fix those things they will loose big in the future since C# and other languages are not waiting to make life of developers more simple. Its just sad to see the decline in the last 10 years since i work daily with Java.
I have commented between codes:
public class Main {
public static void main(String[] args) {
// This is local variable.
// Look! you have declared it within the "body of a method".
// Local variables must be initialized.
int a;
System.out.println(a);
}
}
Now the next one
public class Main {
//This is NOT a local variable. It is NOT in a method body!
//Look! you have defined it as class member ( or a property).
//Java is more generous with local variables and initiates them.
//(ex: int with 0, boolean with false, String(or any object) with null, ...)
static int a;
public static void main(String[] args) {
System.out.println(a);
}
}
I'm reading up on Java and I am scratching my head as to why System.out.println("a: " + a); does not yield a compilation error. Where is a ever initialized?
public class localVariableEx {
public static int a;
public static void main(String[] args) {
int b;
System.out.println("a: " + a);
System.out.println("b: " + b); //Compilation error
}
}
The relevant rules of this are described in the JLS § 4.12.5 Initial Values of Variables (emphasis mine):
Each class variable, instance variable, or array component is initialized with a default value when it is created (§15.9, §15.10): [...]
[...]
A local variable (§14.4, §14.14) must be explicitly given a value before it is used, by either initialization (§14.4) or assignment (§15.26), in a way that can be verified by the compiler using the rules for definite assignment (§16).
So while instance variables (such as a) automatically get a default value, local variables (such as b) don't get one and must not be used unless the compiler can verify that a value has been assigned to them.
b is a variable defined in the method scope only, so the compiler can know that no one initialized it before, but a is a public variable that might be initialized somewhere else.
a is of a primitive type int which will get initialized immediately, which means:
Static class members: get init'ed when the class is loaded (most of the time, when the before main(), but it depends on when the class is loaded).
class S {
static int a;
}
Non-Static class members: get init'ed when the object is. (most of the time after new, but there're other, more advanced, methods to new an object).
class S {
int a;
}
Local variables: should be init'ed in the method's scope before first use.
class S {
void foo() {
int b = 0;
}
}
edited after being corrected...
public class testtype
{
private int a;
private double b;
testtype(int a,double b)
{
this.a=a;
this.b=b;
}
public void maketoequal(testtype oo)
{
oo.a=this.a;
oo.b=this.b;
}
void trytoequal(int c)
{
c=this.a;
}
public static void main(String[] args)
{
testtype t1,t2;
t1=new testtype(10,15.0);
t2=new testtype(5,100.0);
t1.maketoequal(t2);
System.out.println("after the method is called:"+"\n"+"the value of a for t2 is:"+t2.a
+"\n"+"the value of b for t2 is :"+t2.b);
int c=50;
t1.trytoequal(c);
System.out.println("the value of c after the method be called is:"+c);
}
}
why the c is not changed?
Java passes parameters by value (so a copy of the value is made and used locally in the method).
For a primitive type -- c in your case --, the value is the value of c, so your using a copy of the value of c and you don't change c
For an object the value is the value of the reference so even if you pass it by value (copy it) it still references the same object and you can change the object using your copy of the reference...
Java is strictly pass-by-value
Because primitive parameters are passed by value to the method, and so the value you change is local to the method.
You probably want
c = thistest.getA()
where getA() returns the value of a.
In java, parameters are passed by value, not by reference, so what you are doing in "trytoequal" won't work.
See these explanations on java variables value: http://www.yoda.arachsys.com/java/passing.html
Primitive datatypes are passed by value and not by reference, meaning that the c you get in "trytoequal" is a variable whose scope is just within the method and its value is a copy of the method parameter.
The value of c in the method is changed, and then discarded.