What does double initialization mean in Java methods - java

I only use double initialization in java for classes
ex:new ArrayList(){{add()}}
But I recently wrote a code as below by mistake and JVM did not get angry for my mistake.
public void test(){
{
{
....
}
}
}
After that made a simple example and saw the following but still didn' t understand anything expect order of running statements.
public class HelloWorld{
public static void main(String []args){
HelloWorld hw=new HelloWorld();
hw.test1();
System.out.println("----------");
hw.test2();
}
public void test1(){
{
{
System.out.println("1");
}
System.out.println("2");
}
System.out.println("3");
}
public void test2(){
System.out.println("a");
{
System.out.println("b");
{
System.out.println("c");
}
}
}
}
Result:
1
2
3
----------
a
b
c
So my question is that what does double or triple etc initializations mean in Java?

This is not double brace initilization. This is a block statement. From the docs:
A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is allowed.
A block statement encloses the statements within it in a different scope. So if you did:
public static int foo() {
{
int foo = 0;
}
return foo;
}
foo would not be in scope in the line return foo; and you would get an error
In your code, these nested blocks make no difference, as you are just printing, but each block will have a different scope

Related

Why does printing a static variable value gives error in static block while assigning it doesn't

public class ABC {
static {
System.out.println(i);
}
static int i=10;
static {
System.out.println(i);
}
public static void main(String[] args)
{
System.out.println(3);
ABC a = new ABC();
}
}
gives error;
can not reference a field before it is defined
But following -
public class ABC {
static {
i=20;
System.out.println(ABC.i);
System.out.println(i); //same error as above
}
static int i=10;
static {
System.out.println(i);
}
public static void main(String[] args)
{
System.out.println(3);
ABC a = new ABC();
}
}
doesn't throw any error and compiles and runs fine. Even if I use,
package com.sample.package2;
public class ABC {
static {
System.out.println(ABC.i);
}
static int i=10;
static {
System.out.println("yahan 10" + i);
}
public static void main(String[] args)
{
System.out.println(3);
ABC a = new ABC();
}
}
runs fine. Confused as why this error is coming up. There are similar questions asked and it might sound duplicate to some of you but haven't found a clear answer on it yet. What is the order of initialization. I believed static block executes first before anything else. If I shift the static int i=10; error goes away. Does static variable initialize before static blocks?
What you have used is called as " static initialization block ". If you have read the documentation of initializing fields, you will encounter the following (emphasis on mine)
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.
In your code, you have declared and initialized i after trying to call it. If you have done that before the static initialization, the variable i is then not defined.
static {
System.out.println(i); // <-- where is i ?
}
static int i=10;
The use of ABC.i before defining the i in the class works because when you are calling ABC, the class ABC is being initialized. You have to look at when an initialization occurs. If you check JLS 12.4.1, you will notice
A class or interface type T will be initialized immediately before the first occurrence of any one of the following:
...omitted...
A static field declared by T is used and the field is not a constant variable
...omitted...
which means that ABC is being initialized. However, during the initialization, the static { ... } methods are not called anymore because it's used one time. Here, the error isn't thrown. Hence it is possible to retrieve the assigned value when calling ABC.i in the static { ... } method, even if i is defined after that method.
static {
System.out.println(i);
}
static int i=10;
You are intializing the variable later but calling it before.So it throws an error
wheras
static {
i=20;
System.out.println(i);
}
and
static {
System.out.println(ABC.i);
}
static int i=10;
i is initialized first then it is called.

Static nested class can't use print

I have a static nested class StatClass, the file name is Example.java
class OuterClass
{
public static class StatClass
{
System.out.println("Hello"); // This line doesn't work
void pow()
{ System.out.println("Hello W");}
}
}
public class Example
{
public static void main(String[] args)
{
OuterClass.StatClass statInner1 = new OuterClass.StatClass();
statInner1.pow();
}
}
The first println statement doesn't work in the static nested class i.e if its removed then the program compiles, although the println statement works when inside the pow() method, couldn't understand this
Like in a normal class, you can't just put statements inside a class. You could put it in an initializer-block like this:
{
System.out.println("Hello");
}
Or in a constructor, or a method. Whatever you want.
I am just uniting the two answers so far:
one option is a static block
class OuterClass
{
public static class StatClass
{
static {
System.out.println("Hello"); // This line doesn't work
}
void pow()
{ System.out.println("Hello W");}
}
}
public class Example
{
public static void main(String[] args)
{
OuterClass.StatClass statInner1 = new OuterClass.StatClass();
statInner1.pow();
OuterClass.StatClass statInner2 = new OuterClass.StatClass();
statInner2.pow();
}
}
The main difference is how the block is executed by the JVM. In the first case it is executed once during the class initialization. Then the output will be :
Hello
Hello W
Hello W
Another option is initializer block in which case the code will be executed on each instantiation of the class.
class OuterClass
{
public static class StatClass
{
{
System.out.println("Hello"); // This line doesn't work
}
void pow()
{ System.out.println("Hello W");}
}
}
public class Example
{
public static void main(String[] args)
{
OuterClass.StatClass statInner1 = new OuterClass.StatClass();
statInner1.pow();
OuterClass.StatClass statInner2 = new OuterClass.StatClass();
statInner2.pow();
}
}
Then the output will be:
Hello Hello W Hello Hello W
Following statement is outside method that wont work
System.out.println("Hello"); // This line doesn't work
You have to wrap these statements inside static block as follows
static{
System.out.println("Hello"); // This line will work
}
this block will execute when JVM create static instances.
System.out.println("Hello");
This does not work because,the control never goes to the line. Unless you define this inside a function and use the object you created to call it OR use the static block which does not require an object to call it OR an initializer block, it will not work. I hope that helps

Circular Dependency in java- Design

How to prevent circular dependency, any design patterns??,otherwise it will cause stack overflow.
I was asked to redesign this.
class A {
static void method(){
B.method();
}
public static void main(String args[]){
method();
}
}
class B {
static void method(){
A.method();
}
}
This is not just circular dependency, this is an infinite recursion.
You will have to define an exit branch in either A.method() or in B.method(), for example:
class B{
static void method(){
if (someCondition) {
return;
}
A.method();
}
}
someCondition is calculated based on the business problem that is solved with this recursion (you know what it is).
At it's current state this is a will recur infinitely since there is no base case defined.
You would need to define atleast one of the methods with a conditional statement in order to make it break out after some state.
static void method(condition){
A.method();
}

Inlining java code using eclipse jdt/ast

I'm trying to inline java method using eclipse jdt/ast.
For example, I'd like to make this code
class Hello {
static void hello() {
System.out.println("hello");
}
public static void main(String[] args) {
hello();
System.out.println("z");
hello();
System.out.println("h");
hello();
}
}
into this.
class Hello {
public static void main(String[] args) {
System.out.println("hello");
System.out.println("z");
System.out.println("hello");
System.out.println("h");
System.out.println("hello");
}
}
I could get the body block of hello() method stored in Block bl.
I also have the body block of main() method stored in Block block, and I could delete hello(); ExpressionStatements in the block.
Then, I need to insert the Block bl to where the hello(); is invoked.
I tried
block.statements().add(position, bl.getAST());
and
block.statements().add(position, bl);
where position is the location of hello() method in statements(), but both of them raises an error.
What might be wrong? As Block is Statement, I guess one can insert Block in Block#statements().
ADDED
Based on sevenforce answer, I could get the block inserted, but I have the { and } included.
class Hello {
public static void main(String[] args) {
{
System.out.println("hello");
}
System.out.println("z");
{
System.out.println("hello");
}
System.out.println("h");
{
System.out.println("hello");
}
}
}
Is there any way to remove them?
ADDED2
With this code:
ASTNode singleStmt = (ASTNode) bl.statements().get(0);
block.statements().add(position, ASTNode.copySubtree(bl.getAST(), singleStmt));
It shows only the first statement in hello() method. For example, with
static void hello() {
System.out.println("hello");
System.out.println("hello2");
}
I have only System.out.println("hello"); inlined.
There are several reasons for add throwing an exception.
Normally the specific exception should give you a hint. E.g. the node to be added must be in the same AST.
In your case I'd guess, that you attempt to add the same block object, which is already used in the MethodDeclaration node of hello() and each node is allowed to have just one parent.
A possible solution to that is copying the node:
block.statements().add(position, ASTNode.copySubtree(bl.getAST(), bl));
For extracting single statements the following should work:
ASTNode singleStmt = (ASTNode) bl.statements().get(0);
block.statements().add(position, ASTNode.copySubtree(bl.getAST(), singleStmt));
To add all statements from the block you can just loop over:
for (int i = 0; i < bl.statements().size(); i++) {
ASTNode singleStmt = (ASTNode) bl.statements().get(i);
block.statements().add(position + i,
ASTNode.copySubtree(bl.getAST(), singleStmt));
}
Instead of adding to the block you might think of replacing the method invocation.
final ASTRewrite rewriter = ASTRewrite.create(compilationUnit.getAST());
rewriter.replace(methodInvocationNode, blockNode, null);

Calling the static methods of a java/groovy object using reflection

I'm working on a groovy unit-testing class that contains a collection of rules for whether or not the contents of a file are correctly formatted. (Not using a proper rules engine, it just takes advantage of Groovy's assertion capabilities to do validation in a way that vaguely resembles what a rules engine would do.) I was thinking that I could create a method called FireAllRules that looks like this:
public static void FireAllRules(File file)
{
for(def method in Class.getMethods)
{
if(method.name.indexOf("rule" == 0) method.invoke(file);
}
}
All the methods that I want the loop to pick up on are static, and I noticed during the debugging process none of my rule methods are included in the Class.getMethods() enumeration. Ideally, I would like to only loop over the methods that I personally wrote into the class rather than sorting through dozens of uninteresting methods that come in along with java.Object. Is there a way to use reflection to iterate over these static methods at runtime?
Given:
class Test {
public static testThis() {
println "Called testThis"
}
public static woo() {
println "Called woo"
}
public static testOther() {
println "Called testOther"
}
}
You can do:
Test.metaClass.methods.grep { it.static && it.name.startsWith( 'test' ) }.each {
it.invoke( Test )
}
To print:
Called testOther
Called testThis
A more generic method to execute the static test methods of a class would be:
def invokeClass( clazz ) {
clazz.metaClass.methods.grep { it.static && it.name.startsWith( 'test' ) }.each {
it.invoke( clazz )
}
}
invokeClass( Test )
Static methods are included in the methods returned by getMethods(). Your issue might be method.name.indexOf("rule" == 0). This should be method.name.indexOf("rule") == 0, or better yet method.name.startsWith("rule").
Also, are your rule methods public? If not, you can use getDeclaredMethods(). To invoke them, you will have to call setAccessible() first.
The java version would be something like this (I've removed the imports and exceptions for clarity).
public class FindAndRunStaticMethods {
public static void main(String[] args) {
fireAllRules();
}
public static void fireAllRules() {
for(Method method : StaticMethodClass.class.getDeclaredMethods()) {
findAndRunRules(method);
}
}
private static void findAndRunRules(Method method) {
if (!Modifier.isStatic(method.getModifiers())) return;
if (!method.getName().startsWith("rule")) return;
if (!method.getReturnType().equals(Void.TYPE)) return;
Class[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) return;
if (!parameterTypes[0].equals(File.class)) return;
method.invoke(null, new File("dummy"));
}
}
A sample test class could look like this
public class StaticMethodClass {
public static void ruleHere(File x) { System.out.println("should print"); }
public static void ruleRun(File x) { System.out.println("should print"); }
public void ruleNotSelected() { System.out.println("not run"); }
}

Categories

Resources