Can variables be abstract in Java? Do constructor support abstract variables? I am not sure but I think the constructor supports static variables. Please clarify my doubt.
In java only classes and methods can be abstract. Variable declarations cannot. However you can have variable declarations whose types are abstract. See example:
public abstract class MyClass { // allowed
public abstract myMethod(); // allowed
public MyClass instance; // allowed
public abstract MyClass instance; // NOT ALLOWED!!
}
The language specifacation lists 7 types of variables:
class variables - declared as static within a class declaration
instance variables - declared within a class declaration without using the static keyword
array components - like i[2] when we create an array like int[] i= new int[5]
method parameters - name argument values passed to a method
constructor parameters - name argument values passed to a constructor
exception-handler parameter - created each time an exception is caught
local variables - declared in a block ({ }) or for statement
You can use all variable types (except #4) in a constructor:
class Demo {
static int demo1 = 0; // class variable
int[] demo2 = new int[5]; // instance variable
Demo(int demo3) { // constructor parameter
try {
int demo4 = // local variable
demo2[2]; // array component
} catch(RuntimeException demo5) { // exception-handler parameter
}
demo2 = new int[]{Demo.demo1}; // using class and instance variable
// in a constructor
}
int method(int demo6) { // method parameter
}
}
The abstract keyword is not allowed for variable declaration.
abstract is a non-access modifier in java applicable for classes, methods but not variables. It is used to achieve abstraction which is one of the pillar of Object Oriented Programming.
Related
Consider the following article from the JLS: §15.9.5.1
When the anonymous class extends an inner class - then for the implicit constructor of the anonymous class - following is the rule regarding the body of the implicit constructor:
The constructor body consists of an explicit constructor invocation (§8.8.7.1) of
the form o.super(...), where o is the first formal parameter of the constructor,
and the actual arguments are the subsequent formal parameters of the constructor,
in the order they were declared.
Following is what we understand from this-:
o - is the instance of the class - that just encloses the super class of the anonymous class.
when we do o.super(...) we are actually invoking the super class of the enclosing instance.
Consider the following program:
class A_ {
public A_(Boolean st){}
public class B_ {
public B_(Integer a){}
public class C_ {
public C_(String str){}
}
}
}
//when creating the anonymous constructor out of C - in a separate class:
public class ThisInAnonymousTesting {
public static void main(String[] args) {
A_.B_.C_ member =
new A_(true)
.new B_(23)
.new C_("Hey"){
};
}
}
Now when we decompile the anonymous class, we get the following:
/**
=== Anonymous class Declaration
*/
import A_.B_;
import A_.B_.C_;
final class ThisInAnonymousTesting$1 extends C_ {
// - Rule : the 1st argument is the class instance which is the enclosing instance
// of the Super class(C in this case) - ie B
ThisInAnonymousTesting$1(B_ x0, String str) {
x0.getClass();
//But the super() invocation here is for the super class - not for the enclosing instance
super(x0, str);
}
}
Following are my questions:
Why do we need to do o.super(...) - when we are already passing the initialized instance of o to the anonymous class constructor?
ie o gets created only when its super classes would have already been called.
The super() call in the constructor is clearly trying to instantiate the class C_ which is fine - as it is the super class for the current anonymous class.
In the decompiled version, what is the need of x0.getClass(); - I mean why does JVM need to do the getClass()?
Not sure if my interpretation of o.super() clause correct?
I think you misunderstood what o.super(...) meant. Statements of the forms:
ExpressionName . [TypeArguments] super ( [ArgumentList] ) ;
Primary . [TypeArguments] super ( [ArgumentList] ) ;
are qualified superclass constructor invocations, and are specified in the explicit constructor invocations section of the JLS.
It does not invoke the superclass constructor of o. It invokes the enclosing class's superclass constructor, with o as the enclosing instance.
Here is a simple example:
class Outer {
public static final Outer OUTER1 = new Outer(1);
public static final Outer OUTER2 = new Outer(2);
public Outer(int x) {
this.x = x;
}
private final int x;
class Inner {
public Inner() {
System.out.println("In Inner constructor, the enclosing instance's field x is: " + x);
}
}
class InnerSubclass extends Inner {
public InnerSubclass() {
OUTER1.super();
System.out.println("In InnerSubclass constructor, the enclosing instance's field x is: " + x);
}
}
}
If you do Outer.OUTER2.new InnerSubclass();, the output is:
In Inner constructor, the enclosing instance's field x is: 1
In InnerSubclass constructor, the enclosing instance's field x is: 2
OUTER1.super(); there invokes the constructor of Inner (with OUTER1 being the enclosing object), not the constructor of Outer. Note that this is different from just doing super();, as that would be using InnerSubclass's enclosing instance to invoke the superclass constructor, whatever that may be, not necessarily OUTER1.
So really what the spec is saying, is that the anonymous constructor will call the superclass' constructor, with the enclosing instance being the first parameter of the anonymous constructor. What is the first parameter of the anonymous constructor? This is stated just a few lines before:
Otherwise, the first formal parameter of the anonymous constructor represents the value of the immediately enclosing instance of i with respect to S
In your case, new A_(true).new B_(23).
So the overall effect of this, is something like this:
final class ThisInAnonymousTesting$1 extends C_ {
ThisInAnonymousTesting$1(B_ o, String str) {
o.super(str); // recall that this calls C's constructor
}
}
// the callsite now becomes like this:
A_.B_.C_ member = new ThisInAnonymousTesting$1(new A_(true).new B_(23), "Hey");
Note: ThisInAnonymousTesting$1 extends C_ isn't valid Java, but it is allowed in bytecode.
In the decompiled code, you see the syntax super(x0, str); because there is no such thing as inner classes in bytecode. The enclosing instances of inner classes are all just translated to a private field, and assigned through the first parameter of the constructor. As a consequence, o.super(...) is really just super(o, ...) if you look at the byte code.
Consider:
class Outer {
class Inner {}
}
Bytecode for Outer$Inner.class is:
class Outer$Inner {
final Outer this$0;
Outer$Inner(Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1 // this.this$0 = Outer parameter (aka enclosing instance)
5: aload_0
6: invokespecial #7 // super()
9: return
}
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.
i'm new in java and i confused for below example
public class Test {
int testOne(){ //member method
int x=5;
class inTest // local class in member method
{
void inTestOne(int x){
System.out.print("x is "+x);
// System.out.print("this.x is "+this.x);
}
}
inTest ins=new inTest(); // create an instance of inTest local class (inner class)
ins.inTestOne(10);
return 0;
}
public static void main(String[] args) {
Test obj = new Test();
obj.testOne();
}
}
why i can't access to shadowed variable in inTestOne() method with "this" keyword in line 8
why i can't access to shadowed variable in inTestOne() method with "this" keyword in line 8
Because x is not a member variable of the class; it is a local variable. The keyword this can be used to access a member fields of the class, not local variables.
Once a variable is shadowed, you have no access to it. This is OK, because both the variable and the local inner class are yours to change; if you want to access the shadowed variable, all you need to do is renaming it (or renaming the variable that shadows it, whatever makes more sense to you).
Note: don't forget to mark the local variable final, otherwise you wouldn't be able to access it even when it is not shadowed.
this. is used to access members - a local variable is not a member, so it cannot be accessed this way when it's shadowed.
I have a static function that takes a parameter called X.
In this static function I create an anonymous class. This class should have a member variable, also called X.
From the functions in the anonymous class, how can I access the function's parameter X?
To illustrate:
class Test {
static void func(final List<T> X) {
new Test() {
final T[] X = ?.X.toArray();
};
}
}
In my real code I want to create an array in my anonymous class from a list argument (via toArray() in the anonymous class's initialisation), and I want to re-use the same variable name rather than using hungarian notation to differentiate them.
This isn't possible in Java. Function parameters have no "namespace" like this which you could use to denote which variable you mean.
The only solution is to create an arbitrary prefix like outerX for the outer parameter or xAsArray for the inner.
If I define a class like following:
public class myClass {
private x = new anotherClass();
private y;
public myClass() {
y = new anotherClass();
}
}
which variable will get instance earlier? x or y?
And, is it unrecommended to assign a variable outside the constructor?
The order of execution is:
Superclass constructor (or chained constructor to the same class)
Instance variable initializers (the expression assigning to x in your code)
Constructor body (the statement assigning to y in your code)
Section 12.5 of the Java Language Specification contains the details.
Whether you assign the variable in the constructor or not is up to you - I quite like a rule of thumb whereby if the initial value doesn't depend on any constructor parameters, and will always be the same for all constructors, use a variable initializer. Otherwise, assign it in a constructor.
Your variables in your code has no types, but x is instantiated first before the constructor is called. (Do a null check for x on constructor to find out).
As for recommendation, it's up to you. One thing, e.g. in JavaBeans, since I usually don't write a default public constructor (with no arguments), I tend to initialize some fields on declaration (if they are needed to be not null). Otherwise, I instantiate them on constructor.
I recommend you test, instead of just getting an answer from someone else:
Make the constructor of anotherClass print the string passed through.
public class myClass {
private anotherClass x = new anotherClass("outside constructor");
private anotherClass y;
public myClass() {
y = new anotherClass("inside constructor");
}
}
And then you can tell us!