Java class casting throws exception - java

I have a super class A, and classes B, C and D that extend A.
class A {}
class B extends A {}
class C extends A {}
class D extends A {}
Then I have a list like this:
[B.class, C.class, D.class]
I take a random item from the list and instantiate it like so:
Object obj = list.get(i).newInstance()
Now I need to pass obj to a method that accepts objects of type A as a parameter.
A a = (A) obj
causes java to throw an exception (Either InstantiationException or IllegalAccessException, I don't know because android studio won't stop at breakpoints inside the catch, and any attempt to save information about the exception from the catch results in null...).
I understand why I can't dynamically specify the new object type and then cast obj to that type, but if they all share the common parent, I don't see why it wouldn't work.
Can anybody enlighten me how to fix what I'm currently doing, or achieve the same thing in a similar way?
Thanks! /Max

The newInstance method can throw an InstantiationException or IllegalAccessException, hence the warning you're probably seeing in your IDE if this call isn't wrapped in a try/catch. Your simple example seems to work fine though.
class A {}
class B extends A {}
class C extends A {}
public class Test {
public static void main(String[] args) throws Exception {
List<Class> list = new LinkedList<Class>();
list.add(B.class);
list.add(C.class);
Object obj = list.get(0).newInstance();
A a = (A) obj;
System.out.println(a instanceof B);
}
}
Prints "true"

In the end this was due to a bug with android studio. Rewriting the code fixed the problem and I wasn't able to reproduce this issue
Other symptoms that future searchers might find useful:
android studio would not stop at breakpoints inside a catch block
Any attempt to save information about the exception inside the catch resulted in null (see example below)
:
Exception ex = null;
try {
// do something that raises an exception
ex = new Exception();
} catch (Exception ex) {
ex = ex;
}
// ex == null
As pointed out by the other answers, what I was describing in my question does not normally raise an exception.

The code seems to be working absolutely fine. I am not understanding your question.
package testplayground;
import java.util.ArrayList;
import java.util.List;
class A {
void print() {
System.out.println("inside A");
}
}
class B extends A {
public void print() {
System.out.println("inside B");
}
}
class C extends A {
public void print() {
System.out.println("inside C");
}
}
class D extends A {
public void print() {
System.out.println("inside D");
}
}
public class TestPlayGround {
public static void main(String[] args) {
try {
List<Class> list = new ArrayList<Class>();
list.add(B.class);
list.add(C.class);
list.add(D.class);
for (Class classObj : list) {
Object obj = classObj.newInstance();
A a = (A) obj;
methodA(a);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void methodA(A a) {
a.print();
}
}
output:-
inside B
inside C
inside D

Related

Cast a class that is dynamically obtained

I am trying to cast a class that I dynamically obtain that has implemented an interface. I have tried the following below but it doesn't seem to work. How I achieve this.
public InterfaceX test(){
InterfaceX x = null;
Class<?> classX = Class.forName("com.TestClassX");
x = (InterfaceX) classX;
return x;
}
EDIT:
I dont want to create an instance, since I am just looking to simply call a static method defined by the interface.
If x is a Class object, you cannot do x.staticMethod(). However, this is possible using reflection.
public interface Interface {
static void method() {
System.out.println("Hello, World!");
}
}
Then, in the main class you can do this.
import java.lang.reflect.*;
public class Main {
public static void invokeMethod(String className) {
try {
Class<?> clazz = Class.forName(className);
Method method = clazz.getDeclaredMethod("method");
method.invoke(null); // null is used for static methods. For instance methods, pass the instance.
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
invokeMethod("Interface");
}
}
This works, but you should generally try to avoid using reflection (anything in java.lang.reflect). Most of the time there is a better solution to the problem you are trying to solve.

Java call method after class is initialized

I have a class X which is extended by various classes. X needs to know each subtype that exists of it at runtime. So my idea was to create a static method "static init()" in X that takes a Class as parameter. The problem is that a subclass of X is required to be initialized via its static-init-blocks before the call to init() happens. X for example may discover some of the static fields of the subclass which may be of any declared type. So take this code for example:
class X {
X() {
/*This would be one idea but does not work
in this concrete example.*/
init(getClass());
}
static void init(Class<? extends X> c) {
if(c.getDeclaredField("a").get(null) == null) {
throw new AssertionError();
}
}
}
class Y extends X {
static X a = new X();
static {
/*Another idea. Works totally fine but
I dont want to trust subclasses that
they do that correctly.*/
init(Y.class);
}
}
So what I am looking for is a way to somehow get my init()-method called as the last step in the static initialization of a class. Or any other way to prevent the AssertionError from happening.
Edit: Because this lead to misunderstanding in the comments, I actually want to do the second thing. I want my method to be called within the static initialization of any class that subclasses my class (either directly or indirectly). I don't know which subclasses exist, I don't know anything about their structure and all assertions must be checked at runtime (via reflection). My class and the subclasses may not even be compiled by the same compiler on the same machine and/or by the same people.
Edit2: Maybe I can build a ClassLoader that is a simple proxy to the System-ClassLoader and replace the System-ClassLoader with it. If the loaded class is then a subclass of my class I can initialize it and call my method. Unfortunately I don't know much about ClassLoaders (yet) and there are not much tutorials or help on the net regarding this topic. So can anyone having experience with custom ClassLoaders tell me if this is possible? What happens if some other library in my classpath does also install a custom ClassLoader at any point in time?
Edit3: What I don't want to do - if there is any other option - is direct byte-code modifications.
This would be an example for your Edit2:
public class ConstraintClassLoader extends URLClassLoader {
public ConstraintClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
}
#Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class c = findLoadedClass(name);
if (c == null) {
try {
c = findClass(name);
} catch (ClassNotFoundException e) {
c = super.loadClass(name, resolve);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
#Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
System.out.println("find " + name);
Class<?> c = super.findClass(name);
Class<?> parent = c.getSuperclass();
while (parent != null) {
if (parent.getName().contains("X")) {
break;
}
parent = parent.getSuperclass();
}
if (parent == null) {
return c;
}
Field declaredField = c.getDeclaredField("a");
declaredField.setAccessible(true);
if (declaredField.get(null) == null) {
throw new AssertionError();
}
return c;
} catch (NullPointerException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException | AssertionError e) {
throw new RuntimeException(e);
}
}
}
I think it does what you describe in Edit2, but it also suffers the weaknesses you mention (will be fragile with other class loading applications such as OSGI, Reflections, AOP, Spring).
To install this class loader you could load the Main class with this class loader and call the main Method on it with Reflection. You can find other more elegant solutions for setting a classloader on the web.
If you have to deal with a lot of reflection stuff i can recommend reflections libary
With which you can do:
Reflections r = new Reflections("package.name");
Set<Class<? extends X>> childs = r.getSubTypesOf(X.class);
X needs to know each subtype that exists of it at runtime.
This can be achieved with following code:
import java.util.HashSet;
import java.util.Set;
public class Main {
public static class X {
private static Set<Class<? extends X>> classes = new HashSet<Class<? extends X>>();
public X() {
classes.add(getClass());
// and here you can check for fields of subclasses
}
}
public static class Y extends X {}
public static void main(String[] args) {
new Y(); new X();
System.out.println(X.classes);
}
}
If you run main method, it will print something like:
[class Main$X, class Main$Y]

How to invoke parent private method from child? [duplicate]

This question already has answers here:
How can a derived class invoke private method of base class?
(7 answers)
Closed 7 years ago.
public class A{
private int getC(){
return 0;
}
}
public class B extends A{
public static void main(String args[]){
B = new B();
//here I need to invoke getC()
}
}
Can you please tell me if it is possible to do sush thing via reflection in java?
class A{
private void a(){
System.out.println("private of A called");
}
}
class B extends A{
public void callAa(){
try {
System.out.println(Arrays.toString(getClass().getSuperclass().getMethods()));
Method m = getClass().getSuperclass().getDeclaredMethod("a", new Class<?>[]{});
m.setAccessible(true);
m.invoke(this, (Object[])null);
} catch (Exception e) {
e.printStackTrace();
}
}
}
EDIT:
This is quiet an old post but adding a few nuggets of advice
Reconsider your design
Calling private method of parent, though possible through Reflection, but should not be done. Calling private methods on parent might leave the class in invalid state and may lead to unexpected behaviors.
You can do it using reflection, but unless there is a very good reason to do so, you should first reconsider your design.
The code below prints 123, even when called from outside A.
public static void main(String[] args) throws Exception {
Method m = A.class.getDeclaredMethod("getC");
m.setAccessible(true); //bypasses the private modifier
int i = (Integer) m.invoke(new A());
System.out.println("i = " + i); //prints 123
}
public static class A {
private int getC() {
return 123;
}
}
You should declare getc protected. That's exactly what it's for.
As for reflection: Yes, it is possible. You'd have to call setAccessible on the method object though. And it's bad style... ;-)
getDeclaredMethod will only return the private methods in the current class not the inherited methods. To achieve it you need to navigate the inheritance graph via the getSuperclass method. Here is a code snippet that does it
private Method getPrivateMethod(Object currentObject) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> currentClass = currentObject.getClass();
Method method = null;
while (currentClass != null && method == null) {
try {
method = currentClass.getDeclaredMethod("getC");
} catch (NoSuchMethodException nsme) {
// method not present - try super class
currentClass = currentClass.getSuperclass();
}
}
if (method != null) {
method.setAccessible(true);
return method;
} else {
throw new NoSuchMethodException();
}
}
you can try like this using reflection:
Method getCMethod = A.class.getDeclaredMethod("getC");
getCMethod.setAccessible(true);
getCMethod.invoke(new A());

Call to super needs try/catch

I am working on an assignment where I am told that I need to create a class (Call it ClassB) that must extend a given class (Call it ClassA). The only problem is that the code inside of the constructor of ClassA may throw an exception, so when I create my constructor for ClassB, I am trying to wrap a try/catch block around the call to super(), but of course, that doesn't work since super has to be the first call.
How can I work around this?
public ClassB extends ClassA {
public ClassB() throws MyClassAException {
super();
}
}
You can add your exception in the throws clause of your sub class constructor: -
class ClassA {
ClassA() throws Exception {
}
}
public class Demo extends ClassA {
Demo() throws Exception {
super();
}
public static void main(String[] args) {
try {
Demo d = new Demo(); // Handle exception here.
} catch (Exception e) {
e.printStackTrace();
}
}
}
ClassB should have a static method
public static ClassB makeClassB() {
try {
return new ClassB();
}
catch(Exception exc) {
// whatever logic you are currently performing to swallow
// presumably you have some default ClassB to return as part of this logic?
}
that will wrap the construction of ClassB with a try/catch. Client code will call makeClassB() and the constructor to ClassB will be private and throwing.

Is it possible in Java to implement something similar to Object.clone()?

The Object.clone() method in Java is pretty special, as instead of returning a copy of the object that is to be cloned with the Object type, it returns the correct Object type. This can be better described with the following code:
class A implements Cloneable
{
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class B extends A {
}
public class MainABC {
public static void main(String[] args) throws CloneNotSupportedException {
B b = new B();
B b1 = (B)b.clone(); //see here that we are using A's .clone(). The only
//thing it does is call Object's clone().
System.out.println(b1.getClass()); //but as we see here, its not an Object
//its a B!
}
}
So, could anyone explain if possible if is there anyway to replicate what happens inside Object.clone()'s method?
It is definitely true that Object.clone() does a few things that simply can not be achieved in Java.
From Josh Bloch on Design: Copy Constructor versus Cloning (emphasis mine):
Object's clone method is very tricky. It's based on field copies, and it's "extra-linguistic." It creates an object without calling a constructor. There are no guarantees that it preserves the invariants established by the constructors.
Object.clone() does something that isn't supposed to be allowed by the language. That is why, among many other reasons, clone() is broken.
(If you haven't already, you should also read his book Effective Java, to understand why he (and many others) think that Java's clone() and Cloneable is broken).
If you just want to create an object of the same class as another arbitrary object, then this is actually quite achievable, with some caveat (namely that not all types are publicly instantiable) by using reflection.
Here's an example of how to use reflection to:
Find out the class of an object at run-time
List its declared fields, methods, and constructors
Find its copy constructor (if any), and tries to invoke it using the given object as
parameter.
import java.lang.reflect.*;
public class NewInstance {
static void print(String label, Object[] arr) {
System.out.println(label);
for (Object o : arr) {
System.out.println(o);
}
System.out.println("---");
}
static Object newInstance(Object o) {
Class<?> c = o.getClass();
System.out.println("Class is " + c);
print("FIELDS:", c.getDeclaredFields());
print("METHODS:", c.getDeclaredMethods());
print("CONSTRUCTORS:", c.getDeclaredConstructors());
try {
Constructor<?> cc = c.getDeclaredConstructor(c);
o = cc.newInstance(o);
} catch (NoSuchMethodException e) {
System.out.println("No copy constructor found!");
} catch (IllegalAccessException e) {
System.out.println("Copy constructor inaccessible!");
} catch (InstantiationException e) {
System.out.println("Instantiation failed!");
} catch (InvocationTargetException e) {
System.out.println("Copy constructor threw " + e.getCause());
}
return o;
}
public static void main(String args[]) {
Object o1 = "hello";
Object o2 = newInstance(o1);
boolean success = (o1 != o2) && (o1.equals(o2));
System.out.println("Attempt " + (success ? "succeeded!" : "failed :("));
}
}
Output:
Class is class java.lang.String
FIELDS:
// (omitted)
METHODS:
// (omitted)
CONSTRUCTORS:
public java.lang.String()
public java.lang.String(java.lang.String) // this is what we're looking for!
// (rest omitted)
---
Attempt succeeded!
Note that this is just an example to show type can be inspected at run time and a copy constructor can be looked for and invoked. As is, it doesn't work if o is an ArrayList, because it has no constructor that takes an ArrayList (it does have one that takes a Collection, which an ArrayList is).
I'll leave it to you as an exercise on how to expand the search for the copy constructor to include these compatible overloads.
I've never heard or seen a language construct that provides you the functionality that clone give you for free.
You can imitate it, but I don't believe you can replicate the behavior.
The Objenesis library can be used to create instances of arbitrary classes even if they do not have a no-args constructor. It uses various tricks for each JVM to accomplish this. You can use that together with a bit of reflection code to copy all field values from the source object to the destination.
I think you have not even tested the code you typed here!
If you try to compile this code you get errors. First of all the return super.clone() gives you an error of "Type mismatch: cannot convert from Object to A"
Second (i will assume this was a mistype) you did not create an instance of B. You said
B = new B();
Even if we change that to
B b = new B();
B b1 = b.clone();
You will get an error because b.clone() will return an instance of class A.
So sorry but you describe does not happen... You need a cast to get what you want.
So to sum up:
public class A extends Object {
public A clone() {
return super.clone(); // Error "Type mismatch: cannot convert from Object to A"
}
public static void main(String[] args) {
B b = new B();
B b1 = b.clone(); // Error "Type mismatch: cannot convert from A to B"
}
}
class B extends A {
}
EDIT: I'm afraid you got it wrong again. What you did returns an instance of B because you cast it to a B instance. It would return B even if you cast something completely different... For instance
B b = (B)(new JLabel());
System.out.println(b.class);
This will print the class of B. Actually it WOULD print the class of B if it ever got there... You will get an exception before it gets there... To have what you want you have to manually override the clone method and provide your own implementation. You question is not valid at all.. You should delete it but you can't since you have upvoted answers... I would vote to close at least...
How about this?
public class A {
public static void main(String[] args) {
B b = new B();
B b1 = (B)b.getNew();
System.out.println(b1.getClass());
}
public Object getNew() {
try {
return getClass().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
class B extends A {
}

Categories