Why do I get different results on variable value? - java

I'm kind of confused about the outputs.
This is the first program.
class A {
private int price;
private String name;
public int getPrice() {
return price;
}
public String getName() {
return name;
}
}
class B {
public static void main(String[] args) {
A a = new A();
System.out.println(a.getName());
System.out.println(a.getPrice());
}
}
This program compile without error. And the variables have values.
output -
null
0
Second program is,
class B {
public void value() {
int x;
System.out.println(x);
}
}
This program won't even compile.
B.java:4: error: variable x might not have been initialized
The question is why these variables act different? What is the reason.
This may be a very simple question. But kindly explain me.
Thanks.

Instance variables are declared inside a class. not within a method.
class A {
private int price; //instance variable
private String name; //instance variable
}
And instance variables always get a default value( integers 0, floating points 0.0, booleans false, String / references null).
Local variables are declared within a method.
class B {
public void value() {
int x; // local variable
}
}
Local variables must be initialized before use.
class B {
public void value() {
int x = 2; // initialize before use it.
System.out.println(x);
}
}

Related

Cannot assign a value to final variable 'name'

Why isn't Java allowing me to initialize final variables indirectly? I don't see why it shouldn't work, I mean the method will always run so what difference does it make if initialized directly or via method?
This code works:
package com.company;
public class Person {
private final String name;
public Person() {
name = "bob";
}
}
This one doesn't. (even if I get rid of IO code and hardcode the value assigned to name)
package com.company;
import java.util.Scanner;
public class Person {
private final String name;
public Person() {
askName();
}
public void askName() {
Scanner scanner = new Scanner(System.in);
name = scanner.nextLine();
}
}
final fields must be set in the constructor. What you can do is the following.
import java.util.Scanner;
public class Person {
private final String name;
public Person() {
name = askName();
}
public static String askName() {
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
}
However, a better option is likely to inject the value you need.
import java.util.Scanner;
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public static Person askName() {
Scanner scanner = new Scanner(System.in);
return new Person(scanner.nextLine());
}
}
This is common sense. You can only initialize a final variable once.
A constructor can only be called once, so, unless the variable is static, it can be initialized here.
But your method can be called unlimited times, which would cause the variable to be re-referenced, which is just what the final keyword is supposed to avoid of happening.
You can assign values to final member variables in 4 places only:
At the point of declaration
In the constructor
In a static initialization block (if the variable is static)
In a initialization block (if the variable is not static)
It is because final variables cannot be initialized in a method. It needs to be initialized in constructor ,while declaring only or in static blocks only.
You can initialize final variable at 4 places.
with declaration
in constructor (only non-static)
in static initializer (for only static)
in instance initializer (only non-static)
static final variable
These variables can be initialized in either the declaration or static initializer.
class Program {
static final int i1 = 10;
static final int i2;
static {
i2 = 10;
}
}
final variable
final variables can be initialized in the declaration, instance initializer, or constructor:
class Program {
final int i1 = 10;
final int i2;
final int i3;
{
i2 = 10;
}
Program() {
i3 = 10;
}
}
Local final variables
These variables can be initialized in the declaration or any place after its declaration. The local final variables must be initialized before they are used.
class Program {
void method() {
final int i1 = 10;
final int i2;
System.out.println(i1);
i2 = 10;
System.out.println(i2);
return ;
}
}

Variable access in another class

I have a variable in x class .And I have another class called "Y" to access the variable. Will it change the value in X class, if the value is incremented in Y class?
Java uses pass by value but we can achieve what you are asking for by passing an object as an argument to a method like this:
public class ClassX {
public int classId;
public ClassX(int id) {
this.classId = id;
}
public void setId(int id) {
classId = id;
}
public int getId() {
return classId;
}
}
public class ClassY {
public static void main(String[] args) {
ClassX cx = new ClassX(100);
ClassY cy = new ClassY();
System.out.println("classId:"+cx.classId);
cy.modifyId(cx); // an object is passed as argument to a method
System.out.println("classId:"+cx.classId);
}
public void modifyId(ClassX classx) {
classx.setId(220);
}
}
Assuming you have it defined like
public int anInteger = 4;
Then yes, it would change.
These are the sorts of things best learned from experimentation, try various ways of structuring the classes, declaring the variable, and accessing it. See what happens.
Yes. All you need is to pass a reference to it to the other class.

Private access errors

I'm having trouble with a problem I'm working on for class.
The errors occurring are
TC1.java:17: error: myQuantity has private access in CheckItem
items[i].myQuantity=quantities[i];
and
TC1.java:20: error: myPrice has private access in CheckItem
a[i]=items[i].myPrice*((items[i].mySalesTax\100)+1);
This is the code I currently have.
public class CheckItem
{
private double myPrice,
mySalesTax;
private int myQuantity = 1;
public CheckItem( double price, double salesTax )
{
myPrice = price;
mySalesTax = salesTax;
}
public int getQuantity()
{
return myQuantity;
}
public void setQuantity( int qty )
{
myQuantity = qty;
}
public double lineItemTotal()
{
return roundMoney((myPrice*myQuantity)*((mySalesTax/100)+1));
}
public static double roundMoney( double amount )
{
return (int)(100 * amount + 0.5) / 100.0;
}
public static void setQuantities( CheckItem[] items, int[] quantities )
{
for (int i=0;i<quantities.length;i++){
items[i].myQuantity=quantities[i];
}
}
public static double[] lineItemTotals( CheckItem[] items )
{
double[] a=new double[items.length];
for (int i=0;i<items.length;i++){
a[i]=items[i].myPrice*((items[i].mySalesTax/100)+1);
}
return a;
}
}
The problem is that static methods can't access private instance variables. Define getters and setters for those variables, and use them:
items[i].setQuantity(quantities[i]);
a[i]=items[i].getPrice()*((items[i].getSalesTax()\100)+1);
and it will work.
This code compiles fine. If you are trying to access private members outside this class you would get private access error during compilation. In that case standard fix is to provide setters and/or getters.
** EDIT **
Seems like there is confusion about allowed access. You can NOT access any instance variables from static methods/context DIRECTLY! But you CAN access instance variables via instance itself as shown here:
class Test {
private int s = 123;
void instPrint() {
System.out.println(s); // fine
}
static void statPrint(Test ss) {
System.out.println(ss.s); // this is fine too!
// System.out.println(s); // does not compile obviously
}
}
This is the same case as in the code above. This has nothing to do with access modifiers because it's all happening in the same class.
Your code declares these two member variables in class CheckItem with the private scope. This means no other classes can access them directly on a CheckItem instance:
private double myPrice,
mySalesTax;
If you want class TC1 to be able to read or modify them, declare them in CheckItem.java as public. Alternatively, and generally a better practice, you could add public methods to CheckItem.java to allow other classes to access their values:
public double getMyPrice() {
return this.myPrice;
}
public void setMyPrice(double price) {
this.myPrice = price;
}
public double getMySalesTax() {
return this.mySalesTax;
}
public void setMySalesTax(double st) {
this.mySalesTax = st;
}
public int getMyQuantity() {
return this.myQuantity;
}
public void setMyQuantity(int newQty) {
this.myQuantity = newQty;
}
Then, in TC1.java you'd use these methods instead of direct access:
items[i].setMyQuantity(quantities[i]);
and
a[i]=items[i].getMyPrice()*((items[i].getMySalesTax()\100)+1);

How to call a variable in another method?

How to call a variable in another method in the same class?
public void example(){
String x='name';
}
public void take(){
/*how to call x variable*/
}
First declare your method to accept a parameter:
public void take(String s){
//
}
Then pass it:
public void example(){
String x = "name";
take(x);
}
Using an instance variable is not a good choice, because it would require calling some code to set up the value before take() is called, and take() have no control over that, which could lead to bugs. Also it wouldn't be threadsafe.
You make it an instance variable of the class:
public class MyClass
{
String x;
public void example(){ x = "name"; } // note the double quotes
public void take(){ System.out.println( x ); }
}
Since they are in different scopes you can't.
One way to get around this is to make x a member variable like so:
String x;
public void example(){
this.x = "name";
}
public void take(){
// Do stuff to this.x
}
public class Test
{
static String x;
public static void method1
{
x="name";
}
public static void method2
{
System.out.println(+x);
}
}

Java: Anonymous inner class using a local variable

How can I get the value of userId passed to this method in my anonymous inner subclass here?
public void doStuff(String userID) {
doOtherStuff(userID, new SuccessDelegate() {
#Override
public void onSuccess() {
Log.e(TAG, "Called delegate!!!! "+ userID);
}
});
}
I get this error:
Cannot refer to a non-final variable userID inside an inner class defined in a different method
I'm pretty sure I can't assign it as final since it's a variable with an unknown value. I had heard that this syntax does preserve scope in some way, so I think there must be a syntax trick I don't quite know yet.
As everyone else here has said, local variables have to be final to be accessed by an inner class.
Here is (basically) why that is... if you write the following code (long answer, but, at the bottom, you can get the short version :-):
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
foo = new Foo()
{
public void bar()
{
System.out.println(x);
}
};
foo.bar();
}
}
the compiler translates it roughly like this:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
class $1
implements Foo
{
public void bar()
{
System.out.println(x);
}
}
foo = new $1();
foo.bar();
}
}
and then this:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
final int x;
Foo foo;
x = 42;
foo = new $1(x);
foo.bar();
}
private static class $1
implements Foo
{
private final int x;
$1(int val)
{
x = val;
}
public void bar()
{
System.out.println(x);
}
}
}
and finally to this:
class Main
{
public static void main(String[] args)
{
final int x;
Main$Foo foo;
x = 42;
foo = new Main$1(x);
foo.bar();
}
}
interface Main$Foo
{
void bar();
}
class Main$1
implements Main$Foo
{
private final int x;
Main$1(int val)
{
x = val;
}
public void bar()
{
System.out.println(x);
}
}
The important one is where it adds the constructor to $1. Imagine if you could do this:
class Main
{
private static interface Foo
{
void bar();
}
public static void main(String[] args)
{
int x;
Foo foo;
x = 42;
foo = new Foo()
{
public void bar()
{
System.out.println(x);
}
};
x = 1;
foo.bar();
}
}
You would expect that foo.bar() would print out 1 but it would actually print out 42. By requiring local variables to be final this confusing situation cannot arise.
Sure you can assign it as final - just put that keyword in the declaration of the parameter:
public void doStuff(final String userID) {
...
I'm not sure what you meant about it being a variable with an unknown value; all that final means is that once a value is assigned to the variable, it cannot be re-assigned. Since you're not changing the value of the userID within your method, there's no problem making it final in this case.
In Java 8, this has changed a little bit. You can now access variables that are effectively final. Relevant snippet and example from the Oracle documentation (emphasis mine):
However, starting in Java SE 8, a local class can access local
variables and parameters of the enclosing block that are final or
effectively final.
Effectively final: A non-final variable or parameter whose value is never changed after it is initialized is effectively final.
For example, suppose that the variable numberLength is not declared final, and you
add the highlighted assignment statement in the PhoneNumber
constructor:
PhoneNumber(String phoneNumber) {
numberLength = 7; // From Kobit: this would be the highlighted line
String currentNumber = phoneNumber.replaceAll(
regularExpression, "");
if (currentNumber.length() == numberLength)
formattedPhoneNumber = currentNumber;
else
formattedPhoneNumber = null;
}
Because of this assignment statement, the variable numberLength is not
effectively final anymore. As a result, the Java compiler generates an
error message similar to "local variables referenced from an inner
class must be final or effectively final" where the inner class
PhoneNumber tries to access the numberLength variable:
if (currentNumber.length() == numberLength)
Starting in Java SE 8, if you declare the local class in a method, it
can access the method's parameters. For example, you can define the
following method in the PhoneNumber local class:
public void printOriginalNumbers() {
System.out.println("Original numbers are " + phoneNumber1 +
" and " + phoneNumber2);
}
The method printOriginalNumbers accesses the parameters
phoneNumber1 and phoneNumber2 of the method validatePhoneNumber
What's the problem with making it final as in
public void doStuff (final String userID)
declare the method
public void doStuff(final String userID)
The value needs to be final so that the compiler can be sure it doesn't change. This means the compiler can bind the value to the inner class at any time, without worrying about updates.
The value isn't changing in your code so this is a safe change.

Categories

Resources