Update: this is more-or-less a dupe, and it turns out to be compiler magic adding a constructor to pass in the local variable in build2.
Given an interface like such:
public interface IFoo {
public int get();
}
The code below prints 1, 1, 2 and then throws an exception when trying to call getClass().newInstance() on the value returned by build2, but does not when calling the same on the returned value of build1. Any ideas why?
public class Foo {
public static IFoo build1() {
return new IFoo() { public int get() { return 1; } };
}
public static IFoo build2(final int v) {
return new IFoo() { public int get() {return v;} };
}
public static void main(String[] args) throws Exception {
IFoo foo, bar;
foo = build1();
System.out.println(foo.get());
bar = foo.getClass().newInstance();
System.out.println(bar.get());
foo = build2(2);
System.out.println(foo.get());
bar = foo.getClass().newInstance();
System.out.println(bar.get());
}
}
My debugger indicates that in the newInstance() call, getConstructor0 is throwing a NoSuchMethodException.
Here's what happens:
newInstance() requires a nullary constructor
when you create an anonymous class that is accessing a final variable, a field is actually implicitly created to hold this value, which is initially passed to its implicit constructor
thus, the IFoo created in build2 does NOT actually have a nullary constructor
Here's a snippet to show what's going on:
import java.lang.reflect.*;
public class Foo {
interface IFoo { public int get(); }
public static IFoo build2(final int v) {
return new IFoo() { public int get() {return v;} };
}
public static void main(String[] args) throws Exception {
Class<?> klazz = build2(42).getClass();
for (Constructor<?> c : klazz.getDeclaredConstructors()) {
System.out.println(c);
}
// prints: Foo$1(int)
}
}
It shows that Foo$1 (the assigned binary name for the anonymous IFoo class) has only one constructor, and it takes an int. This is how it can return v, because what's returned is actually whatever is assigned to the implicitly created field by this implicitly created constructor.
It is instructive to decompile the Foo$1 (using e.g. javap -c) to see what bytecode gets generated. You will see that in fact this is what happens when a final variable is accessed by an anonymous class.
Related questions
Why am I having this InstantiationException in Java when accessing final local variables?
Related
I can't seem to use getConstructor for constructors with no parameters.
I keep getting the following exception:
java.lang.NoSuchMethodException: classname.<init>()
Here is the code:
interface InfoInterface {
String getClassName();
String getMethodName();
String getArgument();
}
class asa implements InfoInterface {
#Override
public String getClassName() {
return ("jeden");
}
#Override
public String getMethodName() {
return ("metoda");
}
#Override
public String getArgument() {
return ("krzyk");
}
}
class Jeden {
Jeden() {
System.out.println("konstruktor");
}
public void Metoda(String s) {
System.out.println(s);
}
}
class Start {
public static void main(String[] argv) {
if (argv.length == 0) {
System.err.println("Uzycie programu: java Start nazwa_klasy nazwa_klasy2...");
return;
}
try {
for (int x = 0; x < argv.length; x++) {
Class<?> c = Class.forName(argv[x]);
InfoInterface d = (InfoInterface) c.newInstance();
String klasa = d.getClassName();
String metoda = d.getMethodName();
String argument = d.getArgument();
Class<?> o = Class.forName(klasa);
// o.newInstance();
Constructor<?> oCon = o.getConstructor();
System.out.println("ASD");
Class<?> p = (Class<?>) oCon.newInstance();
}
} catch (Exception e) {
System.out.println(e);
}
}
}
o.newInstance(); prints "konstruktor" without problems.
The problem is clear when you read the javadoc of .getConstructor():
Returns a Constructor object that reflects the specified public constructor of the class represented by this Class object.
Emphasis mine.
In your code, the constructor is not public!
Example:
// Note: class is NOT public -- its default constructor won't be either
final class Test
{
public static void main(final String... args)
throws NoSuchMethodException
{
// throws NoSuchMethodException
Test.class.getConstructor();
}
}
Obligatory link to an SO answer which also gives the JLS reference. In particular, note that the default constructor has the same access modifier as the class.
It seems as if your class provides a constructor that is NOT a default constructor. The call to getConstructor() without parameters requires the class to have a default constructor. The following test illustrates this.
import org.junit.Test;
public class ConstructorTest {
public static class ClassWithParameterizedConstructor {
public ClassWithParameterizedConstructor(final String param) {
// A parameterized constructor, no default constructor exists
}
}
#Test
public void testFoo() throws NoSuchMethodException {
// Parameterized constructor lookup works fine
ClassWithParameterizedConstructor.class.getConstructor(String.class);
// This doesn't work since there is no default constructor
ClassWithParameterizedConstructor.class.getConstructor();
}
}
So, a possible solution is to either change the call to getConstructor() to include the correct type or to provide a default constructor on the object itself (but why would you do that?).
Read this: http://docs.oracle.com/javase/tutorial/reflect/member/ctorInstance.html
It seems that both classes Class and Constructor have the method newInstance the difference is that in the Class class you can only call newInstance with no arguments, so the called constructor must have an no arguments (this also brings a problem when you have more that one constructor).
The methoe newInstance in the Constructor class allows you to call the constructor with arguments also, notice that you can also use the method getConstructors instead of getConstructor that returns you all the class constructors and allows you to call the constructor method you want.
In this case, since you only have one constructor only and with no arguments, Class.newInstance works fine. To use the getConstructor to have the same result you'll need to add in the end oCon.newInstance();
You can use getDeclaredConstructors() which returns an array of Constructor objects reflecting all the constructors declared by the class represented by this Class object
class SomeClass{
{
System.out.println("I'am here!");
}
}
public class Main {
public static void main(String[] args) throws Exception{
System.out.println(Arrays.toString(SomeClass.class.getDeclaredConstructors()));
// returns public, protected, default (package) access, and private constructors
// System.out.println(SomeClass.class.getConstructor());
// in that case you got:
// NoSuchMethodException: reflection.SomeClass.<init>()
// because SomeClass don't have public constructor
for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
constructor.newInstance();
}
}
}
And if you have private constructor like this:
class SomeClass{
private SomeClass(String val){
System.out.println(val);
}
}
You have to set accessible for constructor:
constructor.setAccessible(true);
And get something like this:
class SomeClass{
private SomeClass(String val){
System.out.println(val);
}
}
public class Main {
public static void main(String[] args) throws Exception{
for (Constructor constructor : SomeClass.class.getDeclaredConstructors()){
// constructor.newInstance("some arg"); // java.lang.IllegalAccessException
constructor.setAccessible(true);
constructor.newInstance("some arg");
}
}
}
Note: if your class declared as private his default constructor must be private too.
And be careful with nonstatic-inner classes, which receives an outer class instance
In this (somewhat convoluted) scenario, it's actually possible to get hold of the (non-public) constructor by replacing:
Constructor<?> oCon = o.getConstructor();
with
Constructor<?> oCon = o.getDeclaredConstructor();
The "default" visibility of the Jeden class (and its constructor) makes it accessible to the Start class, since it's defined in the same package.
I've inherited some code, and I'm trying to refactor it in an attempt to clean it up.
This is a simplified case of how I received the code:
public class Foo
{
private void doSomething()
{
someOtherAction(Foo.this);
}
protected class FooChildClass
{
protected void anotherAction()
{
createDialogBox(Foo.this);
}
}
}
//totally not related to class Foo even though most code is duplicated
public class Bar
{
private void doSomething()
{
someOtherAction(Bar.this);
}
protected class BarChildClass
{
protected void anotherAction()
{
createDialogBox(Bar.this);
}
}
}
Now, here's the catch - after further examination of the code, Bar is almost a carbon-copy of Foo with some slight changes here and there.
I'd like to condense my code into something like this:
//superclass
public class Foo
{
protected void doSomething()
{
someOtherAction(Foo.this);
}
protected class ChildClass
{
protected void anotherAction()
{
createDialogBox(Foo.this);
}
}
}
//inherits from Foo and only overrides when necessary
public class Bar extends Foo
{
//rely on base implementation of doSomething
//override other functions only when necessary
}
Will my condensed code run successfully? I have a C# background, so I understand a good bit of Java syntax, but C# doesn't have anything similar to ClassName.this.
I'm figuring that ClassName.this is meant to resolve scoping issues by defining what 'this' is intended - and that with my modified code, Bar is indeed a Foo object too - but I figure I would ask to be sure!
Edited original question for clarification
Foo.this is equivalent to this. Therefore your condensed code is Okay with no requirement of being changed.
The following test code is to test your updated program:
Foo f = new Foo();
Foo.ChildClass fc = f.new ChildClass();
f.doSomething();
fc.anotherAction();
Bar b = new Bar();
Bar.ChildClass bc = b.new ChildClass();
b.doSomething();
bc.anotherAction();
The output is:
Foo#52e922
Foo#52e922
Bar#25154f
Bar#25154f
Referring to your most recent edit I composed the following example:
public class Foo {
public void printMe() {
System.out.println("I'm foo");
}
public class Child {
public void printMe() {
Foo.this.printMe();
}
}
}
public class Bar extends Foo {
#Override
public void printMe() {
System.out.println("I'm bar");
}
}
public class Main {
public static void main(String[] args) {
new Bar().new Child().printMe();
}
}
The result was:
I'm bar
Which concludes, that Foo.this.printMe() does not statically refer to the outer class Foo, but to the outer instance of the Child instance, which in this case is an instance of Bar.
For further reading:
The Classname.this syntax is used for inner classes.
You can use the following example to try a bit around and see its effects:
public class Foo {
private int value = 1;
public class Bar {
private int value = 2;
public void printValue() {
System.out.println(Foo.this.value);
}
}
}
Regarding derivation, there's no way to explicitly refer to a certain super type in java, like in C. However, you can refer to your super class using the super keyword.
With java 1.8 and default interface methods, the Classname.super syntax was introduced:
public interface Foo {
default int getValue() {
return 1;
}
}
public interface Bar {
default int getValue() {
return 2;
}
}
public class Impl implements Foo, Bar {
#Override
public int getValue() {
return Bar.super.getValue();
}
}
However, you can still only refer to direct super types. Everything other will be denied by the compiler.
I need to overwrite a constructor of a final class in Java. I know this isn't ideal, but it's unfortunately necessay. Is there any clever workaround to be able to achieve this? Specifically, there is a method that is called from inside the constructor in the final class, where I need to call with a different parameter (now it is called with a constant defined in the package of the final class).
It isn't just not ideal, it's not possible because it is final. Your best option would be to create a wrapper class:
class WrapperClass {
private FinalClass finalClass;
public WrapperClass() {
finalClass = new FinalClass();
}
public void doStuff() {
finalClass.doStuff(); // <- this would be the final method you want to override
// Do your own stuff
}
}
There is no good trick to circumvent final methods, but there is a good trick against (static or not) final fields. If changing that constant you talked about is an option, then you can do that by using reflection:
private static void setDefault(String newDefault) throws Exception {
Field staticField = SomeFinalClass.class.getDeclaredField("CONSTANT");
setValue(null, staticField, newDefault);
}
protected static void setValue(Object owner, Field field, Object value) throws Exception {
makeModifiable(field);
field.set(owner, value);
}
/**
* Force the field to be modifiable and accessible.
*/
protected static void makeModifiable(Field nameField) throws Exception {
nameField.setAccessible(true);
int modifiers = nameField.getModifiers();
Field modifierField = nameField.getClass().getDeclaredField("modifiers");
modifiers = modifiers & ~Modifier.FINAL;
modifierField.setAccessible(true);
modifierField.setInt(nameField, modifiers);
}
}
Note: obviously such a trick should be handled with care and avoided if there is a regular design pattern available.
If the class you want to modify has an interface, you can use java.lang.reflect.Proxy:
public class ProxyTest {
#Test
public void proxy() throws Throwable {
InvocationHandler handler = new MyInvocationHandler(new MyClass());
MyInterface f = (MyInterface) Proxy.newProxyInstance(MyClass.class.getClassLoader(),
new Class[] { MyInterface.class },
handler);
int result = f.test();
assertThat(result).isEqualTo(20);
}
}
class MyInvocationHandler implements InvocationHandler {
private MyInterface wrappedInstance;
public MyInvocationHandler(MyInterface object) {
this.wrappedInstance = object;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.getName().equals("test")){
return 20;
} else {
return method.invoke(this.wrappedInstance, args);
}
}
}
Working in Java.
I have an abstract class as such:
public abstract class Foo {
protected Logger log = null;
// other stuff
public boolean isLoggerSet() {
return (this.log != null) ? true : false;
}
}
Now i extend this class as such:
public class Bar extends Foo {
public Bar() {
this.log = Logger.getLogger(Bar.class);
}
public void someMethod(String[] args) {
Bar b = new Bar();
if(b.isLoggerSet()) {
// do some stuff
}
}
}
The question: Is my Bar.class actually referring to the super.log even though I call this.log since Bar does not have it's own local variable called log? Or would the correct way to implement the isLoggerSet() method be to make it abstract and force Bar.class to implement it itself on it's local copy of log since it's been extended?
Basically I have to say this.log in my Foo class because, it refers to itself. But in Bar class I want to be able to null check log, should I instead be using super.log = in Bar.class?
You have not set your Logger to static, but instead to protected.
Whether you use super or this, they point to the exact same variable in this case.
If there's only one attribute called log in the class hierarchy, it doesn't matter if you say this.log or super.log, it'll refer to the same one - the only one!
this.log is the same super.log. There is only one variable because log is inherited from Foo.
The only one change is required: this.isLoggerSet() should be replaced by b.isLoggerSet()
You cannot call non static method inside static method
Classes are blueprints for making objects. In your case, the blueprint for "Bar" adds on to the blueprint defined in "Foo" (which adds to the blueprint defined in "Object").
Don't let the baseclass confuse you: conceptually here the compiler pulls all the base classes up into one top-level combined class (ignoring the "Object" base):
public class Bar {
protected Logger log = null;
public boolean isLoggerSet() {
return (log != null) ? true : false;
}
public Bar() {
log = Logger.getLogger(Bar.class);
}
public void someMethod(String [] args) {
Bar b = new Bar();
if(b.isLoggerSet()) {
// do some stuff
}
}
}
You would exercise your code like this:
Bar x = new Bar();
x.isLoggerSet(); // Returns true since Bar() constructor just set it
x.someMethod(args);
The first line creates a new object of type "Bar" in memory. This object has a single pointer to a "Logger" object that gets set in the Bar constructor on the first line with "new Bar()".
The next line checks "isLoggerSet". Assuming that "getLogger" returns a live object then the "isLoggerSet" will always return true.
The last line calls "x.someMethod(args)". This method creates a new "Bar" object (whose constructor sets its "log" pointer). Thus the "b.isLoggerSet()" will pass here too.
Here is a slightly modified example:
public abstract class Foo {
protected String name;
public Foo() {
name = "Mr. Foo";
}
}
public class Bar extends Foo {
protected String name;
public Bar() {
name = "Mr. Bar";
}
public void someMethod() {
System.out.println("this.name=" + this.name);
System.out.println("super.name=" + super.name);
}
public static void main(String[] args) {
Bar bar = new Bar();
bar.someMethod();
}
}
Output:
this.name=Mr. Bar
super.name=Mr. Foo
So there are two variables called 'name', one in each class. To access the one in the superclass from within the subclass you need to use 'super.name'.
When creating a Bar() Java checks for a super(...) call to a constructor of the superclass as the first line of the constructor. If it is not there (like above) then 'super();' is invisibly inserted as the first line of the constructor. So I could have written:
....
public Bar() {
super();
name = "Mr. Bar";
}
....
With the same result. However, this is not necessary, Java inserts a super call to the default constructor for you if you don't call a super constructor yourself. In this way constructor chaining is enforced.
If you want to call a super constructor yourself you could also call a non-default constructor, for example:
public abstract class Foo {
protected String name;
public Foo() {
name = "Mr. Foo";
}
public Foo(String name) {
this.name = name;
}
}
public class Bar extends Foo {
public Bar() {
super("Mr. Bar");
}
public void someMethod() {
System.out.println("this.name=" + this.name);
System.out.println("super.name=" + super.name);
}
public static void main(String[] args) {
Bar bar = new Bar();
bar.someMethod();
}
}
Output:
this.name=Mr. Bar // refers to 'name' inherited from Foo
super.name=Mr. Bar // refers to 'name' in superclass, set by the String constructor
// so these both refer to the same variable in this example
Note the default constructor of Foo is not called in this last example.
I'm trying to use reflection to invoke a method whose name and arguments are known at runtime, and I'm failing with an IllegalAccessException.
This is on an object that is an instance of a nonpublic class which implements a public interface, and I've got a brain cramp trying to remember the right way to invoke such a method.
public interface Foo
{
public int getFooValue();
}
class FooImpl implements Foo
{
#Override public int getFooValue() { return 42; }
}
Object foo = new FooImpl();
Given the foo object, how would I call foo.getFooValue() reflectively?
If I look through the results of foo.getClass().getMethods(), this should work but I think it causes the IllegalAccessException Is this a case where I have to call getDeclaredMethods()? Or do I have to walk through the public interfaces/superclasses and call getDeclaredMethods there?
This works:
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Ex
{
public static void main(String[] args) throws Exception
{
final String methodName = "getFooValue";
Object foo = new FooImpl();
Class<?> c = foo.getClass();
Method m = c.getDeclaredMethod(methodName, null);
System.out.println(m.invoke(foo));
}
}
interface Foo
{
public int getFooValue();
}
class FooImpl implements Foo
{
#Override public int getFooValue() { return 49; }
}
I think that you should call the getDeclaredMethods().
Here's an example:
Method methods[] = secretClass.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
By the way, a post refering to 'private classes reflection':
When it comes to bytecode (i.e. runtime) there is no such thing as a private class. This is a fiction maintained by the compiler. To the reflection API, there's a package-accessible type with a public member method.