I'm pretty new to Java, as my post might give away.
I need to create a class (let's call it class A) which uses another class (class B) as one of its fields. Class A's constructor calls class B's constructor. So far things work fine.
But when one of A's methods tries to use one of B's methods on the object of class B, I get a NullPointerException. This is probably too confusing so I wrote this simple example which creates the Exception.
This is class B:
public class class_B {
private int y;
public class_B(int N) {
int y = N*N;
}
public int class_B_method() {
return y;
}
}
and this is class A:
public class class_A {
private class_B obj;
public class_A(int N) {
class_B obj = new class_B(N);
}
public int call_class_B_method() {
return obj.class_B_method();
}
public static void main(String[] args) {
int N =4;
class_A p = new class_A(N);
int a = p.call_class_B_method();
}
}
When I run class_A I get the exception on the line "int a = p.call_class_B_method();".
I don't understand this, since 'obj' should have been created by the constructor 'class_B' and should be available for the method 'call_class_B_method'.
thanks!
This line in the constructor of class_A
class_B obj = new class_B(N);
initializes a local variable obj, not the obj field. This local object class_B gets created, and then almost immediately discarded. Usually compilers warn you of situations like this, for two reasons - first, you have a local variable that "shadows" a field, and second, a local variable is assigned and then never used again.
Change your code to
obj = new class_B(N);
to fix the problem.
This line is wrong(because you lose the reference of the obj):
class_B obj = new class_B(N);
You should write:
obj = new class_B(N);
In the constructor of class_A you're not referencing the field obj, you're creating a new (local) variable with the same name. This is why the member never gets instantiated. You should write obj = new class_B(N) in the contructor.
There are several possible ways to mitigate such kind of errors:
Declare the field obj final, then the compiler will comlain if you don't instantiate it in the constructor. This of course only works when you don't want to change the field value later.
Always use this as identifier: this.obj = new class_B(N). This may clutter the code sometimes, so I guess this is a matter of taste.
Btw. by convention, Java class names always start with a capital letter. But this might be the case only for your example.
Related
How to call the Constructor multiple times using the same object
class a
{
a(int i)
{
System.out.println(i);
}
public static void main(String args[])
{
a b = new a();
int x = 10;
while( x > 0)
{
//Needed to pass the x value to constructor muliple times
}
}
}
I needed to pass the parameter to that constructor.
Constructor of a class A constructs the objects of class A.
Construction of an object happens only once, and after that you can modify the state of the object using methods (functions).
Also notice if programmer does not write any constructor in his class then the Java compiler puts the constructor for the class (public constructor without any parameters) on its own.
In the case where a constructor has been provided by the programmer, the compiler does not create a default constructor. It assumes, the programmer knows and wants creation of the objects of his/her class as per the signature of the explicit constructor.
Constructor calls are chained. Suppose there exists below class relationship.
Child.java extends Parent.java and Parent.java extends GrandParent.java.
Now if Child child = new Child(); is done, only one object is created and that is of Child.java, but the object also has all of the features of GrandParent first then with the features of the Parent and then the Child.
Hence first constructor of GrandParent.java is called then Parent.java is called and lastly the constructor of Child.java is called.
Constructors are special and different from other methods.
The intent of constructors is to create the object, so each time you use the new operator, the constructor is called and a new object is created. You can not call the constructor directly. You need the new operator to call it. Even if you see some class defining methods like getInstance(), it still uses the new operator to construct the object and return the created object.
*PS there are ways to create an object without calling constructor (like Serialization) but that is out of context of the discussion here.
Constructors are called only once at the time of the creation of the object.
Can you please be specific about what you want to achieve?
But I think you could try one of the following two things.
Calling the constructor to create a new object and assigning it to the object 'b':
b = new a(1);
Using the setter method:
void setI(int i){
this.i = i;
}
b.setI(1);
int x = 10;
while( x > 0)
{
a b = new a(x);
}
I'm very confused about object:
I'm creating a object Here is my Test Class :
Test.java
public class Test {
public static void main(String[] argc){
Test obj; //1. ---> here object is created
Test obj = new Test(); //2. --> or here object is created
}
}
Please
Every class without a self-coded constructor has the so called default contructor. This one is invisible and would have this code:
public Test() {
}
In line 1 you only declare a variable of type Test.
In line 2 you actually create an object of type Test and assign it to the variable obj.
As explained in this java tutorial, Object creation as three parts:
1. Declaration: To declare obj variable:
Test obj;
It simply declares a variable. For primitive variables, this declaration also reserves the proper amount of memory, but for reference variables it does not create object.
Instantiation: To instantiate obj variable:
Test obj = new Test();
Operator new is required to allocate memroy for the obj and returning the reference to that memory. The new operator also invokes the object constructor.
Initialization: To initialization obj variable it's constructor needs to be called. In Java, constructor is invoked by the new operator. In other languages e.g. C, C++ when you instantiate any variable using malloc it doesn't call constructor, which needs to be called explicitly. However new operator behaves similar.
The first version
Test obj;
just declares obj value, not creates it. You can use it later in your code. Currently it contains null pointer, or points to nothing.
In the second version
Test obj = new Test();
combines declaration (Test obj), creation (new Test() part) and assignment (=).
what is the difference in following two pieces of code:
class B{
B(){}
}
//1)
class A{
B b = new B();
}
//2)
class A{
B b;
{
b = new B();
}
}
what is the difference in initialization in these two ways ? Also if both the statement are in one single class , what would be their sequence of execution and why?
EDIT: Adding some more clarification:
class C{
//1)
int i = 5;
//initializers block
{
i =7;
}
}
What is the sequence of execution for both these two statements ? What is the final value of i ?
UPDATE FOR THE NEW CLEARER QUESTION:
It sees now that I should have added more text to my question. I
wanted to know what would be the sequence of execution in case both
these statements(1 and 2) are in one single class for the same
variable ?
You are interessted something like this:
private class Test {
public String field = new String("1");
{
field = new String("2");
}
}
At first the field get the value 1, after that the constructor will be called and the init block which was placed in the ctor at compile time will be executed so the value of field is "2".
See this example:
http://ideone.com/72uxES
See also this Question and answer:
Default constructor vs. inline field initialization
OLD VERSION
I think you mean something like this:
Object obj = new Object()
Or
Object obj;
{
obj = new Object();
}
The curly brackets define a scope in which the variable life time is given.
Say we have following example:
import java.util.*;
import java.lang.*;
import java.io.*;
class Ideone
{
private static void checkObject(Object obj) {
if (obj == null)
System.out.println("Object is null");
else
System.out.println("Object is not null");
}
public static void main (String[] args) throws java.lang.Exception
{
Object obj;
{
obj = new Object();
checkObject(obj);
}
checkObject(obj);
}
}
The Output is:
Object is not null
Object is not null
But if we change it to:
{
Object obj = new Object();
checkObject(obj);
}
checkObject(obj);
It will not even compile and give these error msg:
Main.java:22: error: cannot find symbol
checkObject(obj);
^
symbol: variable obj
location: class Ideone
1 error
The first declares a variable obj and initialize it inside the scope
because it was outside declared it can be used after the scope.
If it is declared and initialized only in the scope it can be used only inside the scope.
The lifetime is bound to the scope.
If you use the curly brackets to initialize class fields
you are able to use more than one statement to initialize them
but you can also simply create a final method and call the method to initialize the field.
Example for curly brackets and field initialization:
class A {
private String field;
{
StringBuilder builder = new StringBuilder("Text").append(value)
.append(" ")
.append(otherValue);
//make some computations
//append to builder
//add to field
field = builder.toString();
}
Hint:
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
See working example:
http://ideone.com/X42rQI
As you know that the constructor is called when we instantiate a class. Also all classes have top level Class as Object in JAVA. Now whenever we call the constructor of any class for your case A as new A() it leads us to call first super() leading to Object's constructor.
Now in your example1 your variable b is declared and initialised in the class itself. So before the constructor of class A is executed the variable b is initialised i.e. all the code that you write in public A() will be executed after b has been initialised.
In your example2 your variable b is declared in the class but is being initialised in the constructor of A. If you have some code before the line b = new B(); that code would be executed first then the b would be initialised.
See the example below :
Class A{
B b = new B();
public A(){
b == null; //FALSE as it has been already initialised.
}
}
But
Class A{
B b ;
public A(){
b == null; //TRUE as it has not been initialised.
b = new B();
b == null; //FALSE as it has been just initialised.
}
}
I assume it has to do with the following:
Initializing Instance Members
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: initializer blocks and final methods.
Initializer blocks for instance variables look just like static
initializer blocks, but without the static keyword:
{
// whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.
https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Basically it means that all instance variables that are between the brackets will be initialized for all constructors. Even though your classes dont have multiple constructors
added example with multiple constructors
class A{
B b;
int index;
String result;
{
b = new B();
index = 0;
}
public A(int temp){
// nothing
}
public A(int temp, String test){
this.result = test;
}
public int getIndex(){
return index;
}
}
It doesnt matter here which constructor you use, as the initialization between the brackets is copied into both constructors. a.getIndex() will always return '0'
on passing object reference to static method m1() why it does not become null and why last statement doesn't give errror. Output is X
class I {
private String name;
public String name() {
return name;
}
public I (String s) {
name = s;
}
}
class J {
public static void m1 (I i){
i = null;
}
public static void main (String[] arg)
{
I i = new I("X");
m1(i);
System.out.print(i.name());
}
}
Java is pass by value so scope of i is limited to m1()
public static void m1 (I i){ // i is copied from i which is in main method but it is another variable whose scope lies within m1() only
i = null; // original i in main lies in main() method scope
}
If you change name of i in method m1(), confusion will be lesser like :
public static void m1 (I iObj){
iObj = null; // i in main() method still points to Object
}
Java uses pass by value exclusively. Changing the value of i within m1 only changes that parameter's value. It doesn't do anything to the variable i within main.
What may confuse you - it certainly confuses plenty of other people - is that although the arguments are passed by value, if the type of the parameter is a class, then that value is a reference... and indeed the value of the i variable in each case is a reference. That reference is still passed by value - the value of the argument is directly copied as the initial value of the parameter. However, if instead of changing the parameter itself you make a change to the object that the parameter value refers to, that's a different matter:
void foo(StringBuilder builder) {
builder.append("Hello");
}
void bar() {
StringBuilder x = new StringBuilder();
foo(x);
System.out.println(x); // Prints Hello
}
See the Java tutorial on passing information to a method or constructor for more details.
Java is pass by value (Read second answer in the link specially)
I i scope of i is limited to method m1 only.
In execution it looks something like:
`I i` in `m1()` points to `null` reference
I i method reference still points to `new I("X");`
I am making a copy of my object by using clone() method. But when there is modification in the copy the original object is also modified. I have tried to replicate my issue in the following example. Here are 2 classes ClassA and ClassB.
public class ClassB implements Cloneable
{
int num = 0;
byte[] bit = new byte[1];
//Getters and setters have been removed due to space constraint
public Object clone()
{
try
{
ClassB obj = (ClassB)super.clone();
obj.setNum(this.num);
obj.setBit(this.bit);
return obj;
} catch (CloneNotSupportedException e) {
return null; }
}
}
//Here is ClassA whioch contains the main method and uses clone
public class ClassA {
public void cloneMethod(){
ClassB objB = new ClassB();
objB.bit[0] = (byte)0x8;
objB.setNum(5);
ClassB objCopy = null;
objCopy = (ClassB) objB.clone();
if(objCopy.bit[0] != (byte)0x0)
{
objCopy.bit[0] = 0;
}
System.out.println(objB.bit[0]); //At this point the original object value is also modified.
}
public static void main(String args[])
{
ClassA a = new ClassA();
a.cloneMethod();
}
}
Now how to retain the original object value? I know clone has certain disadvantages. I have tried with new key word also but it doesnt help.Please suggest.
in my original code I have to use the original object bit value later for some more calculation and the copy object bit value will be 0.
Thanks.
Don't set bit to the same byte[] as the original object, instead clone it as well:
obj.bit = this.bit.clone();
Also, you don't need to set num, because that will already be set correctly on the object returned by super.clone().
obj.setNum(this.num);
obj.setBit(this.bit);
These two lines of code are (a) redundant and (b) wrong. If you just want the original field values in the clone you don't need this at all, because super.clone() has already done it for you. If your aim is to return an independently-valued object. As bit[] is an array, i.e. an Object, you should clone it too.
You are not cloning your bit array.