Difference between {} and {{}} initialization in Java - java

public class A{
}
A a = new A(){{
final int x = 1; // IT HAS TO BE FINAL HERE. WHY?
}};
A aa = new A(){
int x = 1; // THIS NEED NOT BE FINAL. WHY?
final int y = 1; // STILL FINAL IS ALLOWED HERE. WHY?
public int getX(){
return x;
}
};
Can somebody please answer the questions mentioned inside the snippet?
Thanks

The outer set of {} declares an anonymous subclass
The inner set declares an initialization block within that subclass.
With the following example, it becomes easier to understand what's going on:
List<String> strings = new ArrayList<String>() {{
add("string");
add("another string");
}};
You basically say: I want a subclass of List, which calls method add at initialization.
It's similar to:
List<String> strings = new ArrayList<String>();
strings.add("string");
strings.add("another string");

A a = new A(){{
final int x = 1; // IT HAS TO BE FINAL HERE. WHY?
It needn't.
The difference between the two is that in the first case, you're writing the code used to initialize each object in the double braces. That x is its local variable (doesn't have anything to do with objects of class A).
In the second case, you're defining the classes body. x would be its member variable. If it were static, its class variable. If final a (basically) constant.

I wonder, why would you want to use the first version of the code (the one with {{}}). The x variable declared inside it's not useful at all, it's local only to the block scope in which it was defined, and being inside an anonymous class, you won't be able to reference it anywhere in the code.
And anyway, the first version of x declaration does not need to be final, it compiles just as fine, with or without final.

In your first example the inner braces create something called an instance initializer. It's an obscure way to initialize variables and call instance methods when an object is constructed. So the first example creates an anonymous subclass of A and creates a local variable within the scope of the initializer. It doesn't have to be final.
In the second example you're creating an anonymous subclass of A but not creating an instance initializer, the variables you create are instance variables of the anonymous subclass.

The first instance A a = new A(){{... has an initialisation block inside the declaration. Another way of writing it would be like this:
A a = new A()
{
{
final int x = 1; // This is inside an initialisation block
}
};
Changing the formatting makes it a bit more obvious.

Related

Method local inner class hides method fields

Given the following class definition
public class MethodLocalAccess {
int m = 10;
String show(){
final int m = 20;
final int n = 30;
class MyClass{
int m = 40;
String someOtherMethod(){
return "" + m + n + this.m + MyClass.this.m + MethodLocalAccess.this.m;
}
}
MyClass object = new MyClass();
return object.someOtherMethod();
}
public static void main(String[] args) {
System.out.println(new MethodLocalAccess().show());
}
}
Produces output 4030404010, which is fairly established why. I want to know, if the local-variable final int m = 20; can be accessed inside the inner-class.
Other way around, fields declared in method-local inner-class having same name as that of method-local-variable, will permanently hide the latter.
What are you referring to is called variable shadowing (link).
If a declaration of a type (such as a member variable or a parameter
name) in a particular scope (such as an inner class or a method
definition) has the same name as another declaration in the enclosing
scope, then the declaration shadows the declaration of the enclosing
scope. You cannot refer to a shadowed declaration by its name alone.
Once you shadowed a variable, it is not accessible anymore without explicitly specifying its scope, if possible. The only solution in this case is to rename either outer or inner variable.
No you can't. The variable inside the function completely shadowed and you can't refer it anymore as Java doesn't have a way to refer function context.
However you can access top level variables with the context this even though they shadowed (infact you are not shadowing and creating a local variable with same name).
You can't, because it's shadowed.
You can't even with reflection, because reflection works on the type level, not on the byte-code.
You can, with additional tools, if you play with the generated byte-code.
In your case I don't think you can access the local variable m defined in the show method since you already have it declared in your inner class, therefore shadowing it.
Using constructs like ClassName.this.varName allows you to access only the members of that enclosing class. This means you can't use that type of expression to access shadowed local varibles defined in the method since they aren't members of that class.
Yes, the fields declared in method-local inner-class having same name
as that of method-local-variable, will permanently hide the latter.
We can access the local-variable final int m = 20 inside the
inner-class only if you don't have the instance variable of Myclass,
int m = 40 is absent.

About declaring and initializing primitive variable in different line outside a method

new to the community, and new to the whole programming world.
While I was studying java, I stumbled on a simple question.
In a main method (or any method), I can declare and initialize a primitive variable on different line just fine. Say,
public static void main (Strin[]args){
int age;
age = 42;
}
will complile just fine.
But if I tried this outside a method, as a class variable or instance variable,
public class test {
int age;
age = 42;
}
the code won't compile. It will only work if the variable is declared and initialized in one line. I was wondering why java doesn't allow this outside a method.
A class body can contain variable declarations and method declarations, but no single statements. When would you expect such a statement to be executed? So your initialization has to be either inline with the declaration (as a shortcut) or in some method, e.g. in the constructor, if you want to initialize the variable when creating a new object.
It is a syntax error! Your code does not comply with the Java syntactic and semantics rules as described in Java Language Specification.
You have to initialise it's value inside the constructor (that's the whole point of a constructor), like
public test() {
age = 42;
}
For static variables it's possible to give them a value:
static int age = 42;
Or use a static block:
static {
age = 43;
}

Initializing variables in a class

I'm studying computer engineering, my 2nd semester just began. I've been making Android applications for a few while.
My programming lecturer (teaches C++ (Object Oriented)) said we can't initialize variables in a class unless we use a constructor since there's no memory dedicated to those data members before making an object of that class.
He said this is incorrect:
class example
{
int a = 0;
};
But my experience says something else:
I've made a class in my Android project that keeps my Constants. I don't make any objects of that class. I've initialized variables and never used a constructor. But it works fine:
public class Constants {
public static final int a = 1;
}
I want to know how am I initializing variables when there's no memory dedicated to that variable and how it works.
What part of my story is wrong? I want to know how my code works when there's no memory dedicated to my variables (Constants)?
The Truth
class A {
int a = 0;
};
In-class initializers became legal in C++11; so the only conclusion to draw from what you have said is that your teacher is living in the past.
However, if he is teaching C++03 and not a later revision of the language, he's correct about it being ill-formed.
It is important to note that what he said regarding (non-static) data-members and their lack of storage until an object of such class has actually been created still applies.
An in-class initializer will initialize the data-member during construction, as long as the data-member isn't initialized in the used constructor's mem-initializer (then the latter takes precedence).
struct A {
A () = default;
A (int x) : m (x) { }
int m = 0; // ^ mem-initializer
};
A x; // `x.m` is initialized to `0`
A y (123); // `y.m` is initialized to `123`
Further Reading
cppreference.com - Non-static data members : Member Initialization
He said this is incorrect:
class example
{
int a = 0;
}
Well, yes, it's incorrect, there needs to be a semicolon at the end, after the }.
With that semicolon, this is legal C++11; the = 0 is a non-static data member initializer (NSDMI for short). It's syntatic sugar for performing the equivalent initialization in the constructor.
public class Constants {
public static final int a = 1;
}
static things are per-class, and exists even if no objects of that class is ever created. Non-static things are per-object.

What are Keywords in Java?

I am curious about keywords in Java.
Should I understand it as a class of various methods that get created with every instance of user-defined classes, like the ultimate “super” class? How is it defined in the Java?
So for example, I came across this:
class A {
class B {}
}
A a = new A();
B b = a.new B();
This seems like each class has keyword new as its own method. I would appreciate any insights on how keywords are defined/implemented in Java.
Classes don't have keyword "new" as a personal method or anything like that. It is the Java language itself that has the keyword "new". So in other words you put "new" in the code the compiler would recognize it and instantiate a new Object.
http://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.9- this link is the documentation of Java language, in section 3.9 it shows all the keywords.
Edit:
Like others are saying, what the snippet of code in your question indicates an inner class, so for instance, like it says in http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
public class ShadowTest {
public int x = 0;
class FirstLevel {
public int x = 1;
void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}
public static void main(String... args) {
ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
The following is the output of this example:
x = 23
this.x = 1
ShadowTest.this.x = 0
This shows that the innerclass or class B(FirstLevel) is like or similar to the outer class's variables and methods(for it is associated with the instance of the outer class) of class A(ShadowTest).
As all the languages ,Java has Keywords. Here the new keyword is used for initialization purposes.here the object of the class A is initialised in the first statement. in second statement the object of class B is initialised with class A's object A
Keywords in the simplest words are the predefined words which have some predefined specific meaning and cannot be used for any other purpose.
Check full list of keywords in Java
Now to elaborate this thing I would take example of two keywords, int and float. An int keyword is used to define an integer variable and that is all what a keyword int can do. We cannot use it for any other purpose. Similarly, float keyword can be used to define a float/decimal number variable, nothing else.
int a = 10;
I defined a variable a of integer type.
int float = 20; <----- It won't work.
In this example, I am trying to declare an integer type variable with name float, which is not possible, as float it self is a keyword, so it cannot be used as an identifier.
If we talk about new keyword, then it is used to create objects of any class or I would more precisely say, new keyword allocates memory to the objects at run time.
It is NOT like that every class has its own new keyword. new is Java's keyword so any Java class can use it.
To clarify,
A a = new A();
B b = a.new B();
In the first statement, we are creating an object of class A and as class B is the nested class of class A, so we cannot access it directly. So to access it, we are using the object of class A, which we already have built.

Java Syntactic Sugar

I ran into this block of code today, and I don't know how it works. I know how to make anonymous classes, but I'm used to seeing a method signature and not just a pair of braces. Is the code between those braces put into a static block? Does it go into the constructor? Or is it something else altogether?
conext.checking(new Expectations() {
{ // <- what does this pair of braces do?
oneOf(alarm).getAttackAlarm(null);
}
});
It's an instance initializer that calls the code within the context of the created object.
This is equivalent to
Expectations exp = new Expectations();
exp.oneOf(alarm).getAttackAlarm(null);
conext.checking(exp)
Whoever wrote it might have thought he was being more efficient by not declaring a variable (not true) or that it was cleaner code (I disagree).
The primary place that these initializers are useful like this is when instantiating maps, ie:
Map map = new HashMap() {{
put("key1", "value1");
put("key2", "value2");
}};
which I think actually is slightly more readable.
It is an initializer block, but not necessarily a static initializer block. It is effectively a constructor for an anonymous inner class. You will typically see this "double-brace initialization" pattern to conveniently create and populate collections:
private final Collection<Integer> FIXED_COLLECTION = Collections.unmodifiableCollection(new HashSet<Integer>()
{ // first set of braces declares anonymous inner class
{ add(1); add(2); add(3); } // second set is initializer block
});
It's an instance initialiser (not a static initialiser).
Consider the definition of a class
public class Foo {
private int i = getDefaultValue();
private static int getDefaultValue() {
return 5;
}
}
The call to getDefaultValue() that initalises i is essentially a code block that runs each time an instance of Foo is constructed. The notation extends that function to allow more complex initialisation. E.g.
public class Foo {
private int i;
{
int z = 4 + 5;
i = z + getDefaultValue();
}
private static int getDefaultValue() {
return 5;
}
}
The manner with which it is used in JMock is a trick to give expectations the look of a closure construct.
What's happening ? The outer braces create a new anonymous class derived from Exception. The inner braces define an initialiser and sets the oneOf() etc.
Why do this ? It's a one-liner trick for constructing and initialising an instance of a class. e. you sometimes see something like this:
new HashSet<String>(){{ add("one"); add("two"); }}
to initialise the contents of a collection.
Downsides ? Because you're creating an anonymous class within the containing class, that anonymous class contains a this reference to the outer class implicitly. Not normally a problem, but it can cause issues if (say) you want to serialise a class that you've constructed like this.
It's an initializer block. I can't tell what it does without looking at the rest of the code.
The trick is to imagine "new Expectation()" replaced with "class Something extends Expectation".
Anynoymous inner classes don't have a constructor, so you can define a an instance initilizer like this i.e. the inner set of braces are the instance initializers.
new Expectations() {
{
oneOf(alarm).getAttackAlarm(null);
}
}
The primary motivation behind this, I believe, is to create a new name space, in which names defined in Expection can be referenced more easily.
For example, suppose java.lang.Math is not final,
new Math()
{{
double x = sin(23.65);
double y = log(x);
...
}};
It's almost as if we have something like
with names from Math
{
double x = sin(23.65);
double y = log(x);
...
}

Categories