I am currently evaluating Scala for future projects and came across something strange. I created the following constant for us in a JSP:
val FORMATED_TIME = "formatedTime";
And it did not work. After some experimenting I decided to decompile to get to the bottom of it:
private final java.lang.String FORMATED_TIME;
public java.lang.String FORMATED_TIME();
Code:
0: aload_0
1: getfield #25; //Field FORMATED_TIME:Ljava/lang/String;
4: areturn
Now that is interesting! Personally I have been wondering for quite a while why an inspector needs the prefix get and a mutator the prefix set in Java as they live in different name-spaces.
However it might still be awkward to explain that to the rest of the team. So is it possible to have a public constant without the inspector?
This is because of the Uniform Access Principle, i.e.: Methods and Fields Are Indistinguishable
See this answer
In Scala 2.8.0 this means if you have
a companion object, you lose your
static forwarders)
If you have this in Scala:
//Scala
object CommonControler {
val FORMATED_TIME = "formatedTime";
}
You may use it like this from Java
//Java
// Variables become methods
CommonControler$.MODULE$.FORMATED_TIME();
// A static forwarder is avaliable
CommonControler.FORMATED_TIME();
Also see the book Scala in Depth
Also note the #scala.reflect.BeanProperty for classes.
I had a further look into the decompiled code and noted something else. The variables are not actually static. So my next idea was to use an object instead:
object KommenControler
{
val FORMATED_TIME = "formatedTime";
} // KommenControler
But now things turn really ugly:
public final class ….KommenControler$ extends java.lang.Object implements scala.ScalaObject{
public static final ….KommenControler$ MODULE$;
private final java.lang.String FORMATED_TIME;
public static {};
Code:
0: new #9; //class …/KommenControler$
3: invokespecial #12; //Method "<init>":()V
6: return
public java.lang.String FORMATED_TIME();
Code:
0: aload_0
1: getfield #26; //Field FORMATED_TIME:Ljava/lang/String;
4: areturn
So I get an additional class ending on $ which has a singleton instance called MOUDLE$. And there is still the inspector. So the access to the variable inside a jsp becomes:
final String formatedTime = (String) request.getAttribute (….KommenControler$.MODULE$.FORMATED_TIME ());
This works as expected and I personally can live with it but how am I going to explain that to the team?
Of course if there is a simpler way I like to hear of it.
Related
Given the following enum:
enum Repeat {
Daily,
Weekly,
Yearly
}
I realize we are able to write it this way:
Repeat repeat = Repeat.Daily.Weekly.Yearly.Weekly;
which is equivalent to:
Repeat repeat = Repeat.Weekly;
May I know why such syntax is allowed? Is there a way to let the compiler warn us against this?
This is allowed as Daily, Weekly, Yearly are the static field by default inside the enum and holds the object of Repeat. Also, you will get a warning from the compiler "The static field Repeat.Weekly should be accessed in a static way". It is similar to below lines of code.
class Foo{
public static Foo obj1 = new Foo();
public static Foo obj2 = new Foo();
public static Foo obj3 = new Foo();
}
Foo f = Foo.obj1.obj2.obj3; // will work fine but you will get a warning from the compiler.
Here is some part of bytecode inspection of Repeat enum and from this, it is clear that Enum variable is static and holds the Object of Enum itself.
0: new #1 // class com/java8/demo/Repeat
3: dup
4: ldc #14 // String Daily
6: iconst_0
7: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #19 // Field Daily:Lcom/java8/demo/Repeat;
13: new #1 // class com/java8/demo/Repeat
Enum instance are just static instance of the enum class.
We have two way to access static field of a class:
Via class itselft: Repeat.Daily
Via instance of class: Repeat.Daily.Daily
When you chain your enum:
Repeat repeat = Repeat.Daily.Weekly.Yearly.Weekly;
It's just like get a static field from an instance of a class.
Is there a way to let compiler warn us against this?
Yes, use a good IDE and turn on warning. That way, you'll be notified as soon as your write the code, before you even compile it.
E.g. in Eclipse, it is called "Non-static access to static member":
Enum literals are static members, and with each static member, one can access them either using the class reference:
TypeName.staticMember
TypeName.staticMethod()
Or on an instance:
new TypeName().staticMember
new TypeName().staticMethod()
The second approach is discouraged (and the compiler will issue a warning)
As enum literals are just static members, Repeat.Daily.Weekly.Yearly.Weekly is like the second code snippet above, accessing static members on instance references.
With a class, that would be:
class Type {
static Type INSTANCE1, INSTANCE2, INSTANCE3;
}
And one can get a reference to INSTANCE3 using Type.INSTANCE1.INSTANCE2.INSTANCE3. It's valid, but it's bad practice.
This question already has answers here:
Use of uninitialized final field - with/without 'this.' qualifier
(4 answers)
Closed 8 years ago.
I wrote this piece of code and it seems compiler allows accessing uninitialized blank final field when accessed using 'this' keyword:
public class TestClass
{
public final int value1;
public int value2;
TestClass(int value) {
value2 = 2 + this.value1; // access final field using 'this' before initialization gives no compiler error
//value2 = 2 + value1; // uncomment it gives compile time error - variable value1 might not have been initialized
value1 = value;
}
public static void main(String args[]) {
TestClass tc = new TestClass(10);
System.out.println("\nTestClass Values : value1 = " + tc.value1 + " , value2 = " + tc.value2);
}
}
I tried compiling it on 1.5, 1.6, & 1.7 and got same result in all three of them.
To me it looks like compiler bug because compiler must throw error in this case but with 'this' keyword it doesn't and thus creates scope of coding error as it will go unnoticed by the programmer since no compile-time or run-time error will be thrown.
FEW POINTS WHY IT IS NOT A DUPLICATE
- all answers are explaining how it works and what JLS says, fine, but my real intent here is should that be allowed at the first place?
- my question here is more from programmer's point of view and not language semantics
This is not a bug. This a feature for Java Specification 1.6 and lower.
The final field can be accessed at any part of the code. There is no restriction about it.
The only restriction in case of final is that it has to be initialized before class instance is created.
When you use this, you express that it is element of the object that is being constructed.
Since the specification 1.7 because of change we may say that this is bug in some implementation of compilers.
But since 1.8 the code will produce same error for this.value1 or value1.
In Java ints have a default value of 0, so even if you did not initialize it, the compiler has still assigned 0 as value.
Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type.
Source: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Note that this does not apply to local variables, only field variables have a default value.
I used the following code
public class HelloWorld {
public final int value1;
public int value2;
public HelloWorld(int value){
System.out.println(this.value1);
System.out.println(this.value2);
value1 = value;
}
public static void main(String args[]) {
}
}
and the bytecode it generates is
Compiled from "HelloWorld.java"
public class test.HelloWorld extends java.lang.Object{
public final int value1;
public int value2;
public test.HelloWorld(int);
Code:
0: aload_0
1: invokespecial #11; //Method java/lang/Object."<init>":()V
4: getstatic #14; //Field java/lang/System.out:Ljava/io/PrintStream;
7: aload_0
8: getfield #20; //Field value1:I
11: invokevirtual #22; //Method java/io/PrintStream.println:(I)V
14: aload_0
15: iload_1
16: putfield #20; //Field value1:I
19: return
public static void main(java.lang.String[]);
Code:
0: return
}
If you notice JVM does a getstatic call in case of final and getfield in case of normal instance variable. Also now if you look at the specs for getstatic it says
On successful resolution of the field, the class or interface that declared the resolved field is initialized (§5.5) if that class or interface has not already been initialized.
So if you use this with a final variable then it is initialize it. Not it will initialize this.value1 and not value1 which is final. You still have to initialize it before using.
in reflection, the private field can be access via getDeclaredField() and setAccessible(true). How to access the private field of a outside class via Objectweb ASM bytecode API?
I set to get the private field from something like, via
Field current = sourceObject.getDeclaredField(privateFieldName);
Field.setAccessible(true);
Type sourceType = Type.getType(sourceObject.getClass());
mv.visitFieldInsn(Opcodes.GETFIELD,
sourceType.getInternalName(),
privateFieldname,
Type.getDescriptor(current.getType()));
When the byte code is executed and to get the private field, I always got an error "java.lang.IllegalAccessError "
Any clue? Thanks a bundle,
You can't do it like that. The setAccessible(true) will only affect the current field-reference in the current execution of your program (that is, it will not affect the execution of the resulting modified program).
To access a private field when running your modified program, you basically have to embed the corresponding reflection-steps into the program.
To access a private field YourClass.thePrivatefield of some object stored in local variable varId you do something like
// Get hold of the field-reference
mv.visitLdcInsn(Type.getType("LYourClass;"));
mv.visitLdcInsn("thePrivateField");
mv.visitMethodInsn(INVOKEVIRTUAL,
"java/lang/Class",
"getDeclaredField",
"(Ljava/lang/String;)Ljava/lang/reflect/Field;");
// Duplicate the reference
mv.visitInsn(DUP);
// Call setAccessible(true) using the first reference.
mv.visitInsn(ICONST_1);
mv.visitMethodInsn(INVOKEVIRTUAL,
"java/lang/reflect/Field",
"setAccessible",
"(Z)V");
// Call get(yourObject) using the second reference to the field.
mv.visitInsn(ALOAD, varId);
mv.visitMethodInsn(INVOKEVIRTUAL,
"java/lang/reflect/Field",
"get",
"(Ljava/lang/Object;)Ljava/lang/Object;");
If the field you're trying to make accessible is part of the cobe base that your'e rewriting, you could obviously also make that field public by using ACC_PUBLIC instead of ACC_PRIVATE.
The actual problem is that you cannot legally access those variables. This is because the JVM defined its access rules before Java had inner classes, so javac creates synthetic accessors for fields that it cannot legally access in the JVM but can in Java. For example,
class Sample {
private int i = 0;
class Inner {
int foo = i;
}
}
Then we can use javap to decompile the generated classes.
fowles#morbo:/tmp$ javap -private Sample
Compiled from "Sample.java"
class Sample extends java.lang.Object{
private int i;
Sample();
static int access$000(Sample);
}
fowles#morbo:/tmp$ javap -c Sample.Inner
Compiled from "Sample.java"
class Sample$Inner extends java.lang.Object{
int foo;
final Sample this$0;
Sample$Inner(Sample);
Code:
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:LSample;
5: aload_0
6: invokespecial #2; //Method java/lang/Object."<init>":()V
9: aload_0
10: aload_0
11: getfield #1; //Field this$0:LSample;
14: invokestatic #3; //Method Sample.access$000:(LSample;)I
17: putfield #4; //Field foo:I
20: return
}
Notice the access$000(Sample) method that got generated in Sample and used from Sample.Inner. Sadly, your options are to either
Make the field accessible
Use reflection
Generate synthetic accessors
maybe it's dumb but is there a difference between
new Something().method();
and
Something tmpSomething = new Something();
tmpSomething.method();
as I was calling only one method on this particular object, I chose the first solution but I'm not sure that this is exactly the same behavior...
I just want to mention the constructor initializes a Writer and method writes in this file...
I did a quick test. This is the extremely trivial test code:
public class TestLiveness
{
public static void test1()
{
System.out.println(new Square(4).square());
count();
}
public static void test2()
{
Square t = new Square(4);
System.out.println(t.square());
count();
}
private static void count()
{
for(int i=0; i<1000000; i++)
System.out.println(i);
}
static class Square
{
private int val;
Square(int val)
{
this.val = val;
}
int square()
{
return val * val;
}
}
}
Javap shows that the two methods are compiled differently; chaining doesn't touch the local variable table whereas the temporary variable does indeed stick around until the method returns. However, the VM/JIT compiler may still perform liveness analysis and allow the instance to be garbage collected before the method returns.
public static void test1();
Code:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
3: new #3; //class TestLiveness$Square
6: dup
7: iconst_4
8: invokespecial #4; //Method TestLiveness$Square."<init>":(I)V
11: invokevirtual #5; //Method TestLiveness$Square.square:()I
14: invokevirtual #6; //Method java/io/PrintStream.println:(I)V
17: invokestatic #7; //Method count:()V
20: return
public static void test2();
Code:
0: new #3; //class TestLiveness$Square
3: dup
4: iconst_4
5: invokespecial #4; //Method TestLiveness$Square."<init>":(I)V
8: astore_0
9: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
12: aload_0
13: invokevirtual #5; //Method TestLiveness$Square.square:()I
16: invokevirtual #6; //Method java/io/PrintStream.println:(I)V
19: invokestatic #7; //Method count:()V
22: return
There is no difference whatsoever except that in the second case you have an unnecessary variable lying around that makes the code harder to maintain.
Also, objects that get created only to be discarded after calling a single method constitute a code smell.
They are the same. Although constructing an object and only calling a single method on it may indicate poor design. Why not allow Something.method(); without needing to expose a constructor?
Well, in the second case you've got the object tmpSomething so you can use it throughout in the code but in the first example you don't. So you can't.
I imagine the first method is probably a touch more efficient but probably not the best practice for Java conventions.
If you can get some value from the first call maybe you might want to define your method static:
public static ____ method() {
}
There is a subtle difference between the two snippets, but only when viewed within their scope. Consider them within methods:
public void doSomething1() {
new Something().method();
doSomeLongRunningSomething();
}
public void doSomething2() {
Something tmpSomething = new Something();
tmpSomething.method();
doSomeLongRunningSomething();
}
In the first method, the 'something' is immediately available for garbage collection while in the second method, tmpSomething stays within scope during the run of doSomeLongRunningSomething. If you are doing anything interesting during the finalize (e.g. closing the file), this could introduce some quirks.
That said, my preference is for the second example and naming the new instance as it assists the debugging processing. While stepping through code you have a named instance that is easier to watch. That doesn't apply when you're getting pre-existing instances in which case I find chaining methods more readable, e.g. myDog.getEyes().getLeftEye().getColorAsRgb().getRed().
Firstly I'll agree with everyone else and say they are the same in terms of function.
However, I'm of the opposite opinion on what most are saying in this post, which is that I think the first example is the way to go.
And with the first example, I'd extend it even further with some form of dependency injection. This will get you in the habit of giving you the ability to test things if you need to inject a mock/test version of that 'Something' class.
Also by not train wrecking (doing more than one operation on the one line which is a code smell, e.g. new dog().getEyes().getColour();), in my opinion improves readability as well as optimises your ability to refactor later on. Just because at the moment you only call that one method on that object doesn't mean you won't need that object to do something else on it later meaning you will have to extract a variable for that 'Something' object anyway.
Nothing wrong with that, even when you call only one function.
Have a look at Fluent Interfaces on Wikipedia or Fluent Interfaces by Martin Fowler
When the Java compiler autoboxes a primitive to the wrapper class, what code does it generate behind the scenes? I imagine it calls:
The valueOf() method on the wrapper
The wrapper's constructor
Some other magic?
You can use the javap tool to see for yourself. Compile the following code:
public class AutoboxingTest
{
public static void main(String []args)
{
Integer a = 3;
int b = a;
}
}
To compile and disassemble:
javac AutoboxingTest.java
javap -c AutoboxingTest
The output is:
Compiled from "AutoboxingTest.java"
public class AutoboxingTest extends java.lang.Object{
public AutoboxingTest();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_3
1: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: astore_1
5: aload_1
6: invokevirtual #3; //Method java/lang/Integer.intValue:()I
9: istore_2
10: return
}
Thus, as you can see, autoboxing invokes the static method Integer.valueOf(), and autounboxing invokes intValue() on the given Integer object. There's nothing else, really - it's just syntactic sugar.
I came up with a unit test that proves that Integer.valueOf() is called instead of the wrapper's constructor.
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import org.junit.Test;
public class Boxing {
#Test
public void boxing() {
assertSame(5, 5);
assertNotSame(1000, 1000);
}
}
If you look up the API doc for Integer#valueOf(int), you'll see it was added in JDK 1.5. All the wrapper types (that didn't already have them) had similar methods added to support autoboxing. For certain types there is an additional requirement, as described in the JLS:
If the value p being boxed is true, false, a byte, a char in the range \u0000 to \u007f, or an int or short number between -128 and 127, then let r1 and r2 be the results of any two boxing conversions of p. It is always the case that r1 == r2. §5.1.7
It's interesting to note that longs aren't subject to the same requirement, although Long values in the -128..127 range are cached in Sun's implementation, just like the other integral types.
I also just discovered that in my copy of The Java Programming Language, it says char values from \u0000 to \u00ff are cached, but of course the upper limit per the spec is \u007f (and the Sun JDK conforms to the spec in this case).
I'd recommend getting something like jad and decompiling code a lot. You can learn quite a bit about what java's actually doing.