I have a question when I saw "Instance variables can be declared in class level before or after use." in the site java_variable_types
I don't understand what is the class level and the meanning of this sequense.
I think they mean that this is legal:
public class Test {
private int someValue;
public int myMethod() {
return someValue + anotherValue;
}
private int anotherValue;
}
(And it is!)
However, I think it is a mistake for the site to describe this as "[i]nstance variables can be declared in class level before or after use".
The phrase "declared in class level" is bad English grammar.
The phrase "in class level" is ambiguous. It could mean declared in the body of a class. However, it could also mean declared as "class-level" (i.e. static) variables. (That is contradictory, and incorrect, but ...)
The phrase "before or after use" is ambiguous. It could mean before or after in the source code file. It could also mean in before or after in the temporal sense. (That would be incorrect. At runtime, all of an object's instance variables are declared and initialized before the code in a method or constructor body is executed.)
While what they are trying to say (I think) in that sentence is correct, they have expressed themselves poorly, and it is clearly causing confusion for some readers.
Instance variable val is declared in line #2( please note the marking) but referenced even before in line #1. You can remove comment from line #3 and comment line #2. Then also it will work.
It means variable val using in line #1 even before declare in case if line#2 consider using after if you consider line#3.
public class prog{
//private int val; //line# 3
public int getVal()
{
return val;//line# 1
}
private int val; //line# 2
prog()
{
val=0;
}
public static void main( String [] args)
{
prog obj= new prog();
System.out.println("val:"+obj.getVal());
}
}
While your reference does a good job of explaining it, I'll add some details for completeness.
An instance variable...
is declared at the class level
can have any visibility that is necessary (public, protected, private, or no modifier to signify package-private)
will receive an initial value after instantiation (that is, you don't have to instantiate the field with a value...but if you don't instantiate a reference value, you may run into a NullPointerException)
The phrase "before or after use" doesn't make much sense, but let's illustrate a scenario:
public class Foo {
private String word;
public void printTheWord() {
System.out.println(word);
}
}
word hasn't been instantiated, but we can use it since it's received an initial value of null. This means that we won't get the value we want, but it will compile.
Contrast this with a local variable. The below code won't compile because word hasn't been instantiated.
public class Foo {
public void printTheWord() {
String word;
System.out.println(word);
}
}
The phrase "before or after use." would mean that the instance variable, which is applicable to the class as a whole ,unlike local variable which is restricted only inside of that method.
It can be declared or initialized at the start of the class,which is generally the most likely way.
Other , inside of the class, it can be declared , after the call of the method using it.
Please find the below code snippet to understand the phrase:
public class InstanceVariable {
//declared before
int foo=4;
public void testInstanceVariableUse(){
System.out.println("The total value of the instance variable is "+ (foo+boo));
}
//declared after
int boo=5;
}
class TestInstanceVariable{
public static void main(String[] args){
InstanceVariable instanceVar = new InstanceVariable();
instanceVar.testInstanceVariableUse();
}
}
Output:
The total value of the instance variable is 9
Related
Sorry if this is a repeat, i've tried looking for the answer to my question but could not come across the answer I'm after.
I'm very new at Java (literally started yesterday) and I am trying to understand why if I declare a variable in my class and then assign a value to it in a void method, the value associated with that variable persists beyond the method's scope. My (very) limited understanding of methods is that they have their own scope and I thought the only way to access any variable changes that had been made within a method was to return them at the end of the method. Is this not the case?
Each method in a class will inherit any attribute (variable) or any method that directly belongs to that class. Say
public class Bicycle {
public int gear;
public int speed;
// the Bicycle class has
// two methods
public void setGear(int newValue) {
gear = newValue;
}
public void speedUp(int increment) {
speed += increment;
}
}
Let's get the setGear method
public void setGear(int newValue) {
gear = newValue;
}
As you can see, I can access the 'gear' attribute because it belongs to the Bicycle class. The parameter '(int newValue)' belongs to this method exclusively, meaning I can only access this variable inside this method, like this:
public void setGear(int newValue) {
newValue = gear;
//this wouldn't make much sense logic wise, but it is
//valid code since I can use newValue only inside the setGear method
speedUp(10);
//the method 'speedUp' belongs to the bicycle class, so I can use
//it inside another method belonging to the same class
}
Alternatively, I can use the this keyword to say that I am referring class attributes, like this:
public void setGear(int gear) {
this.gear = gear;
//I am telling the method that the class attribute 'gear' will
//receive my parameter value 'gear'
//this is useful when my parameter variable name has the same
//name as my class attribute
}
Edit: forgot to give credit to the oficial oracle docs https://docs.oracle.com/javase/tutorial/java/javaOO/classes.html
The answer to this is a bit more complex.
First start to distinguish a method from a function.
A method operates on an object instantiated by calling the constructor of the class (e.g. MyClass obj = new MyClass();). From this point, your object has a state expressed by it's member variables (all variables that are not declared static in your class).
Methods (as part of the object) may change this state (unless the corresponding variables are declared final).
To be able to to so, a method inherits the scope of the class, but the variables are bound to the instance of the object, on which the method is called.
So for instance:
public class MyClass {
private int a = 0;
public void aplusplus() {a++;}
}
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();
obj1.aplusplus(); // the a of obj1 is now 1
obj2.aplusplus(); // the a of obj2 is now 1
obj1.aplusplus(); // the a of obj1 is now 2
But beware! There is also a concept called hiding.
If you declare a local variable within the body of a method, it hides the class member variable. Accessing the variable by name results in accessing the local variable, instead of the member variable. This is particuallry interesting when implementing setter methods for private members, where usually the argument of the method (which is a local variable) is named exactly as the member variable. To still access the member variable, you can use this.variablename. For instance:
public class MyClass {
private int a = 0;
public void aplusplus() {a++;}
public void setA(int a) {this.a = a;}
}
You say in your question that you have declared a variable in your class. This means that any value the variable gets set to, (during method invocations), will persist across method invocations. The variable is part of this object, and as such, is referred to as an instance variable.
If you declare variables inside method definitions, they are inside the scope of the method. They are part of this.yourMethod(). These variables are said to be local to the method. You can only use these variables inside the method. The this object does not know they exist.
class Number {
int mark;
}
class One extends Number {
mark = 1; //error: variable mark not initiated.
}
It's because I have to use it in a method:
int getMark( Number n) {
return n.Mark;
//returns 1 if Object passed is of "One" class
}
So why is that error showing in line 5 of first code.
Edit: Typo, It's "Number" only.
Your initialization code in the subclass needs to occur inside a constructor, method, or initializer block. Something like this (using a constructor):
class One extends Number {
public One() {
mark = 1;
}
}
or like this (using an initializer block):
class One extends Number {
{
mark = 1;
}
}
See the Java tutorial topic Initializing Fields for more information. (By the way, Number is a terrible class name because it collides with a class name in java.lang that every Java program implicitly imports.)
It would be better, however, to put the initialization of mark in the code for Number, since it is good programming practice to keep the management of the field in the same class in which it is declared. This can be done by defining an appropriate constructor for Number:
class Number {
int mark;
/** Explicit initialization constructor */
Number(int mark) {
this.mark = mark;
}
/** Default constructor (perhaps not needed?) */
Number() {
// assign default value to mark (if 0 is not a good default)
}
}
class One extends Number {
One() {
super(1); // calls the explicit initialization constructor
}
}
Eventually, you should also give some thought to what access specifiers (public, protected or private) would be appropriate.
As far as referencing the variable in the method getMark, the problem there is that mark is not the same as Mark. Java is case sensitive when it comes to variable names. Rewrite the method to refer to the variable correctly:
int getMark( Number n) {
return n.mark;
//returns 1 if Object passed is of "One" class
}
I would also suggest making getMark() a method of your Number class, rather than an external method. Then you could use n.getMark() instead of getMark(n) to get the current value of mark. You could then declare mark to be private (and perhaps final as well), since encapsulation and immutability are always good things in OOP.
The following does not compile, giving an 'illegal forward reference' message:
class StaticInitialisation {
static
{
System.out.println("Test string is: " + testString);
}
private static String testString;
public static void main(String args[]) {
new StaticInitialisation();
}
}
However, the following does compile:
class InstanceInitialisation1 {
{
System.out.println("Test string is: " + this.testString);
}
private String testString;
public static void main(String args[]) {
new InstanceInitialisation1();
}
}
But the following does not compile, giving an 'illegal forward reference' message:
class InstanceInitialisation2 {
private String testString1;
{
testString1 = testString2;
}
private String testString2;
public static void main(String args[]) {
new InstanceInitialisation2();
}
}
Why do StaticInitialisation and InstanceInitialisation2 not compile, while InstanceInitialisation1 does?
This is covered by section 8.3.3 of the JLS:
Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (ยง6.3). Specifically, it is a compile-time error if all of the following are true:
The declaration of a class variable in a class or interface C appears textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C or a static initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
Use of instance variables whose declarations appear textually after the use is sometimes restricted, even though these instance variables are in scope. Specifically, it is a compile-time error if all of the following are true:
The declaration of an instance variable in a class or interface C appears textually after a use of the instance variable;
The use is a simple name in either an instance variable initializer of C or an instance initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
In your second case, the use isn't a simple name - you've got this explicitly. That means it doesn't comply with the second bullet in the second list quoted above, so there's no error.
If you change it to:
System.out.println("Test string is: " + testString);
... then it won't compile.
Or in the opposite direction, you can change the code in the static initializer block to:
System.out.println("Test string is: " + StaticInitialisation.testString);
Odd, but that's the way it goes.
Lets look at these two example, I guess this will make you clear.
public class InstanceAndSataticInit {
{
System.out.println("Test string is (instance init): " + this.testString);
}
static{
System.out.println("Test string is (static init ): " + InstanceAndSataticInit.testStringStatic);
}
public static String testStringStatic="test";
public String testString="test";
public static void main(String args[]) {
new InstanceAndSataticInit();
}
}
Output:
Test string is (static init ): null
Test string is (instance init): null
And
public class InstanceAndSataticInitVariableFirst {
public static String testStringStatic="test";
public String testString="test";
{
System.out.println("Test string is (instance init): " + this.testString);
}
static{
System.out.println("Test string is (static init ): " + InstanceAndSataticInitVariableFirst.testStringStatic);
}
public static void main(String args[]) {
new InstanceAndSataticInitVariableFirst();
}
}
output :
Test string is (static init ): test
Test string is (instance init): test
So you can say the sequence are like this.
Static variable will be created but not be initialized.
Static initialization will be executed according to the given sequence.
Non Static variable will be created but not be initialized.
Non Static initialization will be executed according to the given sequence.
By sequence I mean appearance in the code.
I guess this steps answer your two not working example StaticInitialisation and InstanceInitialisation2
But in case your second working example InstanceInitialisation1 by using this key word you are actually helping compiler to overlook the textual hierarchy. Same thing happen in case of static when I call InstanceAndSataticInit.testStringStatic in my first example InstanceAndSataticInit
Simple reason - it's too expensive or impossible to analyze and forbid all forward references. e.g.
{
print( getX(); ); // this.x
print( that().x ); // this.x
}
int x;
int getX(){ return x; }
This that(){ return this; }
The spec settles on forbidding some simple cases indicative of common programmer mistakes.
See also Recursive initializer works when I add "this"?
Here what we have to understand is that in 2nd code snippet You are using block and this keyword.
The block executes if object is created.
That means the object is created in heap area.
You are externally using this keyword to get a value of instance variable.
Here object created with default values that will return as value.
With out using this keyword you can't compile 2nd snippet also.
As I read from various Java book and tutorials, variables declared in a interface are constants and can't be overridden.
I made a simple code to test it
interface A_INTERFACE
{
int var=100;
}
class A_CLASS implements A_INTERFACE
{
int var=99;
//test
void printx()
{
System.out.println("var = " + var);
}
}
class hello
{
public static void main(String[] args)
{
new A_CLASS().printx();
}
}
and it prints out
var = 99
Is var get overridden? I am totally confused. Thank you for any suggestions!
Thank you very much everyone! I am pretty new to this interface thing. "Shadow" is the key word to understand this. I look up the related materials and understand it now.
It is not overridden, but shadowed, with additional confusion because the constant in the interface is also static.
Try this:
A_INTERFACE o = new A_CLASS();
System.out.println(o.var);
You should get a compile-time warning about accessing a static field in a non-static way.
And now this
A_CLASS o = new A_CLASS();
System.out.println(o.var);
System.out.println(A_INTERFACE.var); // bad name, btw since it is const
You did not override the variable, you shadowed it with a brand-new instance variable declared in a more specific scope. This is the variable printed in your printx method.
Default signature for any variable in an interface is
public static final ...
So you cannot override it anyhow.
The variable you declared in that interface is not visible to the class that implemented it.
If you declare a variable in an static and final, i.e. a constant, THEN it is visible to implementors.
How can I make scope of a String variable(In Java) global.So that it is accessed from another function
Eg
//String b="null"; I don't want to do this... because if i do this, fun2 will print Null
public int func1(String s)
{
String b=s;
}
public int func2(String q)
{
System.out.println(b);//b should be accessed here and should print value of s
}
Any Help... Thanks
One of the fundamental concepts in OOP is the concept of scope: in almost all cases it is wise to reduce the scope of a variable (i.e. where it is visible from) to its minimum viable range.
I'm going to assume you absolutely require the use of that variable in both functions. Therefore, the minimum viable scope in this case would cover both functions.
public class YourClass
{
private String yourStringVar;
public int pleaseGiveYourFunctionProperNames(String s){
this.yourStringVar = s;
}
public void thisFunctionPrintsValueOfMyStringVar(){
System.out.println(yourStringVar);
}
}
Depending on the situation, you must assess the required scope of a variable, and you must understand the implications of increasing the scope (more access = potentially more dependencies = harder to keep track).
As an example, let's say you absolutely needed it to be a GLOBAL variable (as you call it in your question). A variable with Global scope can be accessed by anything within the application. This is exceptionally dangerous, which I will demonstrate.
To make a variable with global scope (there are no such things as global variables, exactly, in Java), you create a class with a static variable.
public class GlobalVariablesExample
{
public static string GlobalVariable;
}
If I were to alter the original code, it would now look like this.
public class YourClass
{
public int pleaseGiveYourFunctionProperNames(String s){
GlobalVariablesExample.GlobalVariable = s;
}
public void thisFunctionPrintsValueOfMyStringVar(){
System.out.println(GlobalVariablesExample.GlobalVariable);
}
}
This can be exceptionally powerful, and exceptionally dangerous as it can lead to weird behaviour that you do not expect, and you lose many of the abilities that object oriented programming gives you, so use it carefully.
public class YourApplication{
public static void main(String args[]){
YourClass instance1 = new YourClass();
YourClass instance2 = new YourClass();
instance1.pleaseGiveYourFunctionProperNames("Hello");
instance1.thisFunctionPrintsValueOfMyStringVar(); // This prints "Hello"
instance2.pleaseGiveYourFunctionProperNames("World");
instance2.thisFunctionPrintsValueOfMyStringVar(); // This prints "World"
instance1.thisFunctionPrintsValueOfMyStringVar(); // This prints "World, NOT Hello, as you'd expect"
}
}
Always assess the minimum viable scope for your variables. Do not make it more accessible than it needs to be.
Also, please don't name your variables a,b,c. And don't name your variables func1,func2. It doesn't make your application any slower, and it won't kill you to type in a few extra letters.
Hmm. You clearly need some lessons in object-oriented programming. In OO there is no "global" variable. But any variable defined as a member in a class (outside a method) is global within that class.
public class MyClass {
private String myVar; // this can be accessed everywhere in MyClass
public void func1(String s) {
myVar = s;
}
public void func2(String q) { // why is q needed here? It's not used
System.out.println(myVar);
}
}
So func2 will output the value of s ONLY IF you call func1 first.
final Myclass myClass = new MyClass();
myClass.func1("value");
myClass.func2("whatever"); // will output "value"
Also, why are the methods returning int in your example? They should be void.