When I tried to write something like this:
public interface MyInterface {
static {
System.out.println("Hello!");
}
}
the compiler could not compile it.
But when I wrote something like this:
interface MyInterface {
Integer iconst = Integer.valueOf(1);
}
and decompiled it, I saw static initialization:
public interface MyInterface{
public static final java.lang.Integer i;
static {};
Code:
0: iconst_1
1: invokestatic #1; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: putstatic #2; //Field i:Ljava/lang/Integer;
7: return
}
Could you please explain this behavior to me?
Interfaces should not have side-effects and that even applies to static intializers. They would have highly JVM-implementation dependent behavior. Look at the following code
public class InterfaceSideEffects {
public static void main(String[] args) {
System.out.println("InterfaceSideEffects.main()");
Impl i=new Impl();
System.out.println("Impl initialized");
i.bla();
System.out.println("Impl instance method invoked");
Foo f=new Impl();
System.out.println("Impl initialized and assigned to Foo");
f.bla();
System.out.println("Foo interface method invoked");
}
}
interface Foo {
int dummy=Bar.haveSideEffect();
void bla();
}
class Bar {
static int haveSideEffect() {
System.out.println("interface Foo initialized");
return 0;
}
}
class Impl implements Foo {
public void bla() {
}
}
What do you think, when will interface Foo initialized be printed? Try to guess and run code afterwards. The answer might surprise you.
You can have static initialisation, but you cannot have a static block. The fact the static initialisation needs a static code block to implement does change the Java syntax.
The point is you are not meant to have code in an interface (before Java 8) but you are allowed to initialise fields.
BTW you can have a nested class or enum which has as much code as you like and you can call this while initialising a field. ;)
You can get around the problem - if you see it as a problem - by putting a second non-public class in the same file.
public interface ITest {
public static final String hello = Hello.hello();
}
// You can have non-public classes in the same file.
class Hello {
static {
System.out.println("Static Hello");
}
public static String hello() {
System.out.println("Hello again");
return "Hello";
}
}
Testing this with:
public class Test {
public void test() {
System.out.println("Test Hello");
System.out.println(ITest.hello);
}
public static void main(String args[]) {
try {
new Test().test();
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
}
prints:
Test Hello
Static Hello
Hello again
Hello
Java is such a clever language - it makes it difficult to do stupid things but not impossible. :)
Intefaces does not have any initialization blocks. Following code snippet may be helpful..
public interface MyInterface {
public static final int a;// Compilation error as there is no way for
// explicit initialization
}
public class MyClass {
public static final int a;// Still no error as there is another way to
//initialize variable even though they are final.
static{
a=10;
}
}
There is never a point to declaring a static method in an interface. They cannot be executed by the normal call MyInterface.staticMethod(). (EDIT:Since that last sentence confused some people, calling MyClass.staticMethod() executes precisely the implementation of staticMethod on MyClass, which if MyClass is an interface cannot exist!) If you call them by specifying the implementing class MyImplementor.staticMethod() then you must know the actual class, so it is irrelevant whether the interface contains it or not.
More importantly, static methods are never overridden, and if you try to do:
MyInterface var = new MyImplementingClass();
var.staticMethod();
the rules for static say that the method defined in the declared type of var must be executed. Since this is an interface, this is impossible.
You can of course always remove the static keyword from the method. Everything will work fine. You may have to suppress some warnings if it is called from an instance method.
To answer some of the comments below, the reason you can't execute "result=MyInterface.staticMethod()" is that it would have to execute the version of the method defined in MyInterface. But there can't be a version defined in MyInterface, because it's an interface. It doesn't have code by definition.
Related
I just discovered something quite weird. If a final variable is called from the implicit super constructor using an overriden method, the element will never not be initialiazed upon call :
public static abstract class A {
public A()
{
doSomething();
}
public abstract void doSomething();
}
public static class B extends A {
private final Object s = new Object();
public B()
{
}
public void doSomething() {
System.out.println(s);
}
}
public static void main( String[] args )
{
new B();// prints 'null'
}
If the method is not overriden, the final variable will be correctly instanciated :
public static class B {
private final Object s = new Object();
public B()
{
doSomething();
}
public void doSomething() {
System.out.println(s);
}
}
public static void main( String[] args )
{
new B(); // prints the object correctly
}
Finally, even stranger for me (i think this is relative to the String#intern mechanism)
public static abstract class A {
public A()
{
doSomething();
}
public abstract void doSomething();
}
public static class B extends A {
private final String s = "Hello";
public B()
{
}
public void doSomething() {
System.out.println(s);
}
}
public static void main( String[] args )
{
new B(); // will print "Hello"
}
My question is what can i do in the first case to fix this, should i use a getter that ensures non-null value ?
I sort of understand why the first case occurs (the constructor implicitely calls the 'super' constructor before initialization of any instance vars), but, if i am correct, in this case why is the 3rd case prints correctly 'Hello' ?
It's important to understand that constructors of base classes are executed before constructors of subclasses. This means than fields of subclasses may not have been initialized during construction of base classes. (They will however be initialized during construction of the subclasses.)
My question is what can i do in the first case to fix this, should i use a getter that ensures non-null value ?
The problem you've discovered is one of the reasons to never ever call overridable methods from within the constructor.
A getter is probably just as bad, since the getter would also be overridable.
Instead of having
Object s = new Object();
...
public void doSomething() {
System.out.println(s);
}
in B, you can pass the variable to be used in the construction of A as an argument to As constructor:
public B() {
super(new Object());
}
This passes the data relevant for constructing the B object, so that the constructor of B is "self-contained". This is quite messy though, and I would advice you to reconsider the structure of your classes.
Regarding the third case:
private final String s = "Hello";
Since "Hello" is a compile time constant expression, and since s is final, the Java compiler is free to inline the use of s, i.e. replace s with "Hello" at it's discretion.
I have following classes (note that methods are static):
class Base
{
public static void whosYourDaddy()
{
Class callerClass = // what should I write here to get caller class?
System.out.print(callerClass.getName());
}
}
Class A extends Base
{
public static void foo()
{
A.whosYourDaddy();
}
}
Class B extends Base
{
public static void bar()
{
B.whosYourDaddy();
}
}
And when I call:
A.foo();
B.bar();
I'd like to get output:
AB instead of BaseBase. Is it even possible with static methods (in Java 7)?
What you can do, but shouldn't :) is use the Throwable getStackTrace method. Aside from the smell, this is pretty slow, because getting the stack trace isn't that fast. But you will get an array of StackTraceElement, and each one will contain the class of teh class that is calling it (and you can also get the file and line, and if you separate the two with a : you can get a clickable link in eclipse, not that I'd ever do such a thing...).
Something like
String className = new Throwable().getStackTrace()[1].getClassName();
Hope that helps :)
private static class Reflection {
private static final SecurityManager INSTANCE = new SecurityManager();
static Class getCallClass() {
return INSTANCE.getCallClass(2);
}
private Reflection() {
}
private static class SecurityManager extends java.lang.SecurityManager {
public Class getCallClass(int i) {
Class[] classContext = getClassContext();
if (i >= 0 && i + 1 < classContext.length) {
return classContext[i + 1];
}
return null;
}
};
}
Is it even possible with static methods (in Java 7)?
No, Static methods aren't inherited. Only non-static methods are inherited.
In your case change Base (and subclasses) as follows:
class Base
{
public void whosYourDaddy()
{
Class<?> callerClass = getClass();
System.out.print(callerClass.getName());
}
}
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // Here comes Late Static Bindings
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test(); // Outputs "B"
?>
I want to get an equivalent in Java...so something like
class A {
public static void who(){
System.out.println("A");
};
public static void test(){
who(); //<<< How to implement a static:: thing here???
}
}
class B extends A {
public static void who(){
System.out.println("B");
};
public static void main(String[] args){
B.test(); // Outputs "A" but I want "B"
}
}
I want the who() call inside A::test to resolve as in PHP 5.3 by calling B::who.
EDIT: I know there is no "standard way" of doing this in most popular languages. I'm looking for hacks and such. Also, is this possible in C/C++, or any other popular OOP language?
This is not for any real design on anything. I'm just being curious.
Not possible in Java. (At least not without ugly reflection hacks.)
I encourage you to rethink your design and rely on proper objects.
Related question:
Can I override and overload static methods in Java?
Edit: B.test() will (or can at least according to spec) be compiled into a call to A.test(), so there's no way to discover how the call was made from within A.test(). In other words, there's no way to let the behaviour of A.test depend on if it was called through A.test() or B.test().
Since you're asking out of curiosity, here's AFAIK the closest "solution".
Overload test with a test(Class<?> c) which takes as argument the class which defines the intended who method.
Hide (note that you can't override) test() in class B.
And change the implementation of A.test slightly.
In code:
class A {
public static void who() {
System.out.println("A");
}
public static void test() {
test(A.class);
}
public static void test(Class<?> c) {
//who(); //<<< How to implement a static:: thing here???
try {
c.getMethod("who").invoke(null); // Call static who on given class.
} catch (Exception e) {
}
}
}
public class B extends A {
public static void who(){
System.out.println("B");
}
public static void test() {
test(B.class);
}
public static void main(String[] args){
A.test(); // Outputs "A"
B.test(); // Outputs "B"
}
}
It seems that the compiler generates a call to B.test in the bytecode even though B doesn't declare a method named test.
Bytecode of main method:
invokestatic #5 = Method B.test(()V)
return
Given the names of a class and method ("B" and "who") you can easily use reflection to call the method. So the question becomes
Can you extract B by combining the call stack and bytecode inside A.test?
You'll need to use the return address stored on the stack to locate the call to B.test in the bytecode and extract the declared call. There are plenty of bytecode manipulation libraries, but I don't know if any of them allow you to tie that to the execution stack in the JVM.
You can't override static methods in java.
http://geekexplains.blogspot.co.uk/2008/06/can-you-override-static-methods-in-java.html
Here's an example from Java. It uses Java 8 default methods and getClass(). I bet it works with classes too:
interface A {
default String name() {
return getClass().getName();
}
}
class B implements A {}
public class LateBinding {
public static void main(String[] args) {
// Create an anonymous class in `LateBinding` (called `$1`)
System.out.println(new A(){}.name());
// Instantiate a new `B`
B b = new B();
System.out.println(b.name());
}
}
Results:
$ javac LateBinding.java && java LateBinding
LateBinding$1
B
As you can see the method knows in both cases where it's running, although it's defined in A. This example is not really static, because you can't call getClass() statically, but LSB in PHP is not really limited to static contexts.
There is no elegant way to do it with static method declaration (Only Delphi from what I'm aware of supports override for static methods). However if static is not necessary for you you can write something like this:
class A {
public void who(){
System.out.println("A");
};
public void test(){
who(); //<<< How to implement a static:: thing here???
}
}
class B extends A {
#Override
public void who(){
System.out.println("B");
};
public void main(String[] args){
A instance = new A();
instance.test(); // prints 'A'
instance = new B();
instance.test(); // prints 'B'
}
}
EDIT after clarification:
Pretty hacky way of doing this: Thread.currentThread().getStackTrace() then from top-most record get method and class this method belongs to. Having Class c - you could write c.getMethod("who").invoke(null); to call the correspond who() method.
interface TestA {
String toString();
}
public class Test {
public static void main(String[] args) {
System.out.println(new TestA() {
public String toString() {
return "test";
}
});
}
}
What is the result?
A. test
B. null
C. An exception is thrown at runtime.
D. Compilation fails because of an error in line 1.
E. Compilation fails because of an error in line 4.
F. Compilation fails because of an error in line 5.
What is the answer of this question and why? I have one more query regarding this question. In line 4 we are creating an object of A. Is it possible to create an object of an interface?
What you are seeing here is an anonymous inner class:
Given the following interface:
interface Inter {
public String getString();
}
You can create something like an instance of it like so:
Inter instance = new Inter() {
#Override
public String getString() {
return "HI";
}
};
Now, you have an instance of the interface you defined. But, you should note that what you have actually done is defined a class that implements the interface and instantiated the class at the same time.
test should be the output. This is an example of an anonymous inner class.
This is a very common pattern used with the Comparator interface as an emulation of closures.
Try this too... The name of anonymous class is generated!
Inter instance = new Inter() {
public String getString() {
return "HI" + this.getClass();
}
};
The trick is not only about the anonymous inner class, this prints test cause it overrides the toString method and while System.out.println a Object it implicit call it's toString method.
We can create an object of an anonymous class, that implements the interface:
Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.
If you have an interface, that declares one method toString, you can first create a class, that implements this inerface, and then create an object of this class:
interface TestA {
String toString();
}
class TestB implements TestA {
#Override
public String toString() {
return "test";
}
}
public class Test {
public static void main(String[] args) {
System.out.println(new TestB());
}
}
Or you can create an object of an anonymous class to simplify this code:
interface TestA {
String toString();
}
public class Test {
public static void main(String[] args) {
System.out.println(new TestA() {
#Override
public String toString() {
return "test";
}
});
}
}
In both cases it prints "test".
I don't know the significance of this question. If this is an interview question, then I can say it's okay. But in real time it's not the right approach to implement an inheritance.So coming to the answer of the question, here what you are doing is an anonymous inner class .
Here you are instantiating a class and implementing the inheritance by writing,
System.out.println(new TestA() {
public String toString() {
return “test”;
}
});
and ofcourse the result would be test
In Java, I'd like to have something as:
class Clazz<T> {
static void doIt(T object) {
// ...
}
}
But I get
Cannot make a static reference to the non-static type T
I don't understand generics beyond the basic uses and thus can't make much sense of that. It doesn't help that I wasn't able to find much info on the internet about the subject.
Could someone clarify if such use is possible, by a similar manner? Also, why was my original attempt unsuccessful?
You can't use a class's generic type parameters in static methods or static fields. The class's type parameters are only in scope for instance methods and instance fields. For static fields and static methods, they are shared among all instances of the class, even instances of different type parameters, so obviously they cannot depend on a particular type parameter.
It doesn't seem like your problem should require using the class's type parameter. If you describe what you are trying to do in more detail, maybe we can help you find a better way to do it.
Java doesn't know what T is until you instantiate a type.
Maybe you can execute static methods by calling Clazz<T>.doit(something) but it sounds like you can't.
The other way to handle things is to put the type parameter in the method itself:
static <U> void doIt(U object)
which doesn't get you the right restriction on U, but it's better than nothing....
I ran into this same problem. I found my answer by downloading the source code for Collections.sort in the java framework. The answer I used was to put the <T> generic in the method, not in the class definition.
So this worked:
public class QuickSortArray {
public static <T extends Comparable> void quickSort(T[] array, int bottom, int top){
//do it
}
}
Of course, after reading the answers above I realized that this would be an acceptable alternative without using a generic class:
public static void quickSort(Comparable[] array, int bottom, int top){
//do it
}
I think this syntax has not been mentionned yet (in the case you want a method without arguments) :
class Clazz {
static <T> T doIt() {
// shake that booty
}
}
And the call :
String str = Clazz.<String>doIt();
Hope this help someone.
It is possible to do what you want by using the syntax for generic methods when declaring your doIt() method (notice the addition of <T> between static and void in the method signature of doIt()):
class Clazz<T> {
static <T> void doIt(T object) {
// shake that booty
}
}
I got Eclipse editor to accept the above code without the Cannot make a static reference to the non-static type T error and then expanded it to the following working program (complete with somewhat age-appropriate cultural reference):
public class Clazz<T> {
static <T> void doIt(T object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
private static class KC {
}
private static class SunshineBand {
}
public static void main(String args[]) {
KC kc = new KC();
SunshineBand sunshineBand = new SunshineBand();
Clazz.doIt(kc);
Clazz.doIt(sunshineBand);
}
}
Which prints these lines to the console when I run it:
shake that booty 'class com.eclipseoptions.datamanager.Clazz$KC' !!!
shake that booty 'class com.eclipseoptions.datamanager.Clazz$SunshineBand' !!!
It is correctly mentioned in the error: you cannot make a static reference to non-static type T. The reason is the type parameter T can be replaced by any of the type argument e.g. Clazz<String> or Clazz<integer> etc. But static fields/methods are shared by all non-static objects of the class.
The following excerpt is taken from the doc:
A class's static field is a class-level variable shared by all
non-static objects of the class. Hence, static fields of type
parameters are not allowed. Consider the following class:
public class MobileDevice<T> {
private static T os;
// ...
}
If static fields of type parameters were allowed, then the following code would be confused:
MobileDevice<Smartphone> phone = new MobileDevice<>();
MobileDevice<Pager> pager = new MobileDevice<>();
MobileDevice<TabletPC> pc = new MobileDevice<>();
Because the static field os is shared by phone, pager, and pc, what is the actual type of os? It cannot be Smartphone, Pager, and
TabletPC at the same time. You cannot, therefore, create static fields
of type parameters.
As rightly pointed out by chris in his answer you need to use type parameter with the method and not with the class in this case. You can write it like:
static <E> void doIt(E object)
Something like the following would get you closer
class Clazz
{
public static <U extends Clazz> void doIt(U thing)
{
}
}
EDIT: Updated example with more detail
public abstract class Thingo
{
public static <U extends Thingo> void doIt(U p_thingo)
{
p_thingo.thing();
}
protected abstract void thing();
}
class SubThingoOne extends Thingo
{
#Override
protected void thing()
{
System.out.println("SubThingoOne");
}
}
class SubThingoTwo extends Thingo
{
#Override
protected void thing()
{
System.out.println("SuThingoTwo");
}
}
public class ThingoTest
{
#Test
public void test()
{
Thingo t1 = new SubThingoOne();
Thingo t2 = new SubThingoTwo();
Thingo.doIt(t1);
Thingo.doIt(t2);
// compile error --> Thingo.doIt(new Object());
}
}
Since static variables are shared by all instances of the class. For example if you are having following code
class Class<T> {
static void doIt(T object) {
// using T here
}
}
T is available only after an instance is created. But static methods can be used even before instances are available. So, Generic type parameters cannot be referenced inside static methods and variables
When you specify a generic type for your class, JVM know about it only having an instance of your class, not definition. Each definition has only parametrized type.
Generics work like templates in C++, so you should first instantiate your class, then use the function with the type being specified.
Also to put it in simple terms, it happens because of the "Erasure" property of the generics.Which means that although we define ArrayList<Integer> and ArrayList<String> , at the compile time it stays as two different concrete types but at the runtime the JVM erases generic types and creates only one ArrayList class instead of two classes. So when we define a static type method or anything for a generic, it is shared by all instances of that generic, in my example it is shared by both ArrayList<Integer> and ArrayList<String> .That's why you get the error.A Generic Type Parameter of a Class Is Not Allowed in a Static Context!
#BD at Rivenhill: Since this old question has gotten renewed attention last year, let us go on a bit, just for the sake of discussion.
The body of your doIt method does not do anything T-specific at all. Here it is:
public class Clazz<T> {
static <T> void doIt(T object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
// ...
}
So you can entirely drop all type variables and just code
public class Clazz {
static void doIt(Object object) {
System.out.println("shake that booty '" + object.getClass().toString()
+ "' !!!");
}
// ...
}
Ok. But let's get back closer to the original problem. The first type variable on the class declaration is redundant. Only the second one on the method is needed. Here we go again, but it is not the final answer, yet:
public class Clazz {
static <T extends Saying> void doIt(T object) {
System.out.println("shake that booty "+ object.say());
}
public static void main(String args[]) {
Clazz.doIt(new KC());
Clazz.doIt(new SunshineBand());
}
}
// Output:
// KC
// Sunshine
interface Saying {
public String say();
}
class KC implements Saying {
public String say() {
return "KC";
}
}
class SunshineBand implements Saying {
public String say() {
return "Sunshine";
}
}
However, it's all too much fuss about nothing, since the following version works just the same way. All it needs is the interface type on the method parameter. No type variables in sight anywhere. Was that really the original problem?
public class Clazz {
static void doIt(Saying object) {
System.out.println("shake that booty "+ object.say());
}
public static void main(String args[]) {
Clazz.doIt(new KC());
Clazz.doIt(new SunshineBand());
}
}
interface Saying {
public String say();
}
class KC implements Saying {
public String say() {
return "KC";
}
}
class SunshineBand implements Saying {
public String say() {
return "Sunshine";
}
}
T is not in the scope of the static methods and so you can't use T in the static method. You would need to define a different type parameter for the static method. I would write it like this:
class Clazz<T> {
static <U> void doIt(U object) {
// ...
}
}
For example:
public class Tuple<T> {
private T[] elements;
public static <E> Tuple<E> of(E ...args){
if (args.length == 0)
return new Tuple<E>();
return new Tuple<E>(args);
}
//other methods
}