I have a piece of code for which i have to know how memory is allocated
public class Demo {
public void checkNullReference(){
ConsumerName name = null;
addReference(name);
System.out.println(name.getConsumerName());
}
public void addReference(ConsumerName name){
name = new ConsumerName();
name.setConsumerName("KRISHNA");
}
public static void main(String []args){
Demo demo = new Demo();
demo.checkNullReference();
}
}
The code is giving null pointer exception i have given a refrence of object to method and there i am allocating new object to it and setting name if i rewrite the method then every thing is working as expected.
public void checkNullReference(){
ConsumerName name = new ConsumerName();
addReference(name);
System.out.println(name.getConsumerName());
}
You cannot change a reference in a calling method from the called method. Thus, with this code:
public void checkNullReference(){
ConsumerName name = null;
addReference(name);
System.out.println(name.getConsumerName());
}
name will still be null after the call to addReference(name), regardless of what addReference does with its formal argument.
You can redesign addReference to return an instance of ConsumerName. While you're at it, you can delete the argument, since it is ignored. The result could be:
public void checkNullReference(){
ConsumerName name = addReference();
System.out.println(name.getConsumerName());
}
public ConsumerName addReference(){
ConsumerName name = new ConsumerName();
name.setConsumerName("KRISHNA");
return name;
}
You are calling addReference() method with a null as input so .. there is no pass by reference happening and ConsumerName is newly getting allocated with in addReference() its scope will remain with in the method only. So you modify your code to return the new instance of ConsumerName .
public class Demo {
public void checkNullReference(){
ConsumerName name = null;
name = addReference(name);
System.out.println(name.getConsumerName());
}
public ConsumerName addReference(ConsumerName name){
name = new ConsumerName();
name.setConsumerName("KRISHNA");
return name ;
}
public static void main(String []args){
Demo demo = new Demo();
demo.checkNullReference();
}
}
Always remember, java uses pass-by-value. When you do
name = new ConsumerName();
name.setConsumerName("KRISHNA");
it just simply creates a new local object which locate inside addReference function stack. So, as soon as the function returned, you lost that object. In another word, your ConsumerName object inside checkNullReference is not the same as the ConsumerName object inside AddReference.
Related
I noticed a scenario today. When we pass a parameter on private methods, the entity will return the revised values but not primitives.
Here is my sample code,
/**
* #author gowthami
*
*/
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
String s = "gowth";
System.out.println("before " + s);
concateMe(s, "ami");
System.out.println("after " + s);
BeanTest bt = new BeanTest();
bt.setId("1");
System.out.println("before");
System.out.println(bt.getId());
System.out.println(bt.getName());
setBeanTestName(bt, "gowthami");
System.out.println("after");
System.out.println(bt.getId());
System.out.println(bt.getName());
String st = new String("gowth");
System.out.println("before " + st);
concateMe(st, "ami");
System.out.println("after " + st);
}
private static void setBeanTestName(BeanTest bt, String string) {
bt.setName(string);
}
private static void concateMe(String s, String string) {
s = s+string;
System.out.println("inside method " + s);
}
}
BeanTest.java
public class BeanTest {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
So the bean is getting updated even though we are not returning it from private method but a string is not. Can someone explain me whats happening on JVM level?
This is because Java follows Call by value, not Call by reference.
When you are passing s you are actually passing value of s, not the actual s. So though you are changing s in concateMe(), it will not change in your main method.
When you are passing bt, then the change is affecting as you are changing the field variable of that reference. But if you change the reference, then there will be no effect. You can add this in main method:
System.out.println("before......");
System.out.println(bt.getId());
System.out.println(bt.getName());
changeBeanTest(bt);
System.out.println("after");
System.out.println(bt.getId());
System.out.println(bt.getName());
Suppose your changeBeanTest is like this:
private static void changeBeanTest(BeanTest tempBeanTest) {
BeanTest bt = new BeanTest();
bt.setId("2");
bt.setName("Trump");
tempBeanTest = bt;
}
run this. There will be no change to bt sent from main().
The Bean is a full object in java passed by reference to the private method so it is the same instance in the main method and the private method.
You are modifying the values of that instance so the changes show up in both places.
The string is more or less a primitive and passed as a copy of the value instead of the exact instance from main. It is a new instance in the private method and so you are modifying a new variable. The changes don't show up in the main method as it is a different entity.
String s = "gowth"; in this line s is pointing to "gowth" from String Pool.When you are calling
private static void concateMe(String s, String string) here String s is different from caller method String s.Here String s scope is local to method ContactMe,But contactMe local String s pointing same "gowth" which is pointed by Caller class String s.After s = s + string;since String is immutable the method local reference String s pointing a different String "gowthami",but caller method String s is still pointing to "gowth".So you are getting this output.
But in case of Bean both the object pointing same String reference,Once we made any change in reference it would be reflected for both object.
public class CopyConstructorEx
{
String web, webb;
CopyConstructorEx(String w){
web = w; }
CopyConstructorEx(CopyConstructorEx je){
webb = je.web; }
void disp(){
System.out.println("Website: "+web); }
public static void main(String args[]){
CopyConstructorEx obj1 = new CopyConstructorEx("BeginnersBook");
CopyConstructorEx obj2 = new CopyConstructorEx(obj1);
obj1.disp();
obj2.disp();
}
}
output:
Website: BeginnersBook
Website: null
Can anyone explain why second output is null?
web being a string type variable is null by default. In your copy constructor, you aren't assigning anything to it, so there's no reason for it to change.
public class TEST {
String name1 = "Kelly";
String name2 = "Christy";
String name3 = "Johnson";
public static void main(String[] args) {
}
public void displaySalutation(String name1) {
displayLetter();
}
public void displaySalutation(String name2, String name3) {
displayLetter();
}
public void displayLetter() {
System.out.println("Thank you for your recent order.");
}
}
The main method needs to make a call to the method containing the print line. This can be done by creating an instance of TEST which contains the methods to print. You then call the methods contained in the instance variable.
I've updated your code to show how to create an instance and call the method.
public class TEST {
String name1 = "Kelly";
String name2 = "Christy";
String name3 = "Johnson";
// Define the entry point
public static void main(String[] args) {
// Create an instance of test
TEST test = new TEST();
/* Call the displayLetter method within TEST
Prints "Thank you for your recent order." */
test.displayLetter();
/* Call the printName method with the "Kelly" String as an argument.
Prints "Kelly" */
test.printName(name1);
}
// Prints a line
public void displayLetter(){
System.out.println("Thank you for your recent order.");
}
// Example print variable
public void printName(String name){
System.out.println(name);
}
}
I've corrected your code so that you can call the displayLetter method but I'm unsure exactly what you would like to do with the other two methods.
One.java
public class One {
String asd;
public class() {
asd="2d6"
}
public static void main(String args[]) {
Two a = new Two();
}
}
Two.java
public class Two {
ArrayList<String>data;
String asd;
public Two(String asd){
this.asd=asd;
data.add(this.asd);
}
}
How do I use this asd value of second for third class calling from first class's main method.
**Third class**
Per comments of #Maroun Maroun and #Bennyz, you can create a getter and setter method in your Two class:
import java.util.ArrayList;
public class Two {
ArrayList<String> data;
String asd;
public Two(String asd) {
this.asd = asd;
data = new ArrayList<>(); //<-- You needed to initialize the arraylist.
data.add(this.asd);
}
// Get value of 'asd',
public String getAsd() {
return asd;
}
// Set value of 'asd' to the argument given.
public void setAsd(String asd) {
this.asd = asd;
}
}
A great site to learn about this while coding (so not only reading), is CodeAcademy.
To use it in a third class, you can do this:
public class Third {
public static void main(String[] args) {
Two two = new Two("test");
String asd = two.getAsd(); //This hold now "test".
System.out.println("Value of asd: " + asd);
two.setAsd("something else"); //Set asd to "something else".
System.out.println(two.getAsd()); //Hey, it changed!
}
}
There are also some things not right about your code:
public class One {
String asd;
/**
* The name 'class' cannot be used for a method name, it is a reserved
* keyword.
* Also, this method is missing a return value.
* Last, you forgot a ";" after asd="2d6". */
public class() {
asd="2d6"
}
/** This is better. Best would be to create a setter method for this, or
* initialize 'asd' in your constructor. */
public void initializeAsd(){
asd = "2d6";
}
public static void main(String args[]) {
/**
* You haven't made a constructor without arguments.
* Either you make this in you Two class or use arguments in your call.
*/
Two a = new Two();
}
}
Per comment of #cricket_007, a better solution for the public class() method would be:
public class One {
String asd;
public One(){
asd = "2d6";
}
}
This way, when an One object is made (One one = new One), it has a asd field with "2d6" already.
I am trying to manipulate an object inside a method like this:
My class Problem:
public class TaxiProblem {
public Problem(final World world, final Agent agent) {
_world = world;
_world.setRandomAgent(_agentPlace);
}
private Place _agentPlace;
// Various other functions
}
and in the function .setRandomAgent() in the class World I am trying to manipulate the Place object in what I want it to be like this:
public void setRandomAgent(Place agentPlace) {
int rand = _random.nextInt(25);
agentPlace = _places.get(rand);
agentPlace.setHasAgent(true);
}
I basically want to grab a random Place from the List _places and have it in the variable agentPlace in .setRandomAgent() which in turn will have it in _agentPlace in the Problem class. I thought this would work since Java passes objects by reference in methods but it didn't and _agentPlace remains null.
By doing this
agentPlace = _places.get(rand);
you are overwriting the reference that was passed to the method and losing access to the object you want to alter.
In your setRandomAgent method, agentPlace is indeed a reference that points to your _agentPlace field, not the field itself. In the line I pasted above, what you do is make that reference point to a different object.
_agentPlace = _world.getRandomAgent();
public Place getRandomAgent() {
int rand = _random.nextInt(25);
Place agentPlace = _places.get(rand);
agentPlace.setHasAgent(true);
return agentPlace();
}
When you pass agentPlace to the method, you are creating a copy of the reference. So if you modify the object, then it would work when you return up the stack. But reassigning the variable makes you lose the object you were working with.
I suspect that your problem lies in the implementations as your understanding of pass by reference I believe is correct. The following code will produce the results you expect - That is, it will first print "Before change", then "I am changed!".
class Program
{
static void Main(string[] args)
{
var problem = new Problem();
}
}
public class Problem
{
public Problem()
{
var toChange = new ClassToChange();
toChange.ChangeMe = "Before change";
Console.WriteLine(toChange.ChangeMe);
var changer = new ClassThatChanges();
changer.ChangeSomething(toChange);
Console.WriteLine(toChange.ChangeMe);
Console.ReadLine();
}
}
public class ClassToChange
{
public string ChangeMe { get; set; }
}
public class ClassThatChanges
{
public void ChangeSomething(ClassToChange classToChange)
{
classToChange.ChangeMe = "I am changed!";
}
}