ok - I am walking a resource tree looking for classes that extend a particular super class, possibly not directly - I have code that works, but I'm having to resolve a concrete class, and I'm just wondering whether the same thing is possible without actually resolving the class - here is my working function:
private static <T> boolean checkInherits(Class<T> superClass, ClassMetadata classInformation)
{
try
{
Class<?> theClass = Class.forName(classInformation.getClassName());
return superClass.isAssignableFrom( theClass );
}
catch (Throwable theException)
{
return false;
}
}
So - is it possible to do that without using class.forName()? ie straight from the class metadata?
There is no way. A (non-final) class Foo cannot "know" about all of its (direct or indirect) subclasses because anyone can create a class that extends Foo. Hence, you can only learn about subclass relationships once you have both Class objects.
Assuming ClassMetadata is from the Spring framework (javadoc), you could use .getSuperClassName() to get the String representation of the superclass, but this won't solve your problem if the subclass relationship isn't direct. The only way to get the Class object from a ClassMetadata is by using Class.forName(classInformation.getClassName()), exactly as you've already done.
Related
public interface A {}
public interface B {}
public class Test implements A{}
public class Test2 {}
I made a method which checks if a class implements an interface. I want my method to only accept generic interfaces and not all class objects.
method
public static boolean containsInterface(Class clazz, Class intf)
{
try
{
Validate.isTrue(intf.isInterface());
if(clazz.isInterface())
return JavaUtil.isClassExtending(intf, clazz);
for(Class c : ClassUtils.getAllInterfaces(clazz))
{
if(JavaUtil.isClassExtending(intf, c))
return true;
}
}
catch(Throwable t)
{
t.printStackTrace();
}
return false;
}
Since Test.class & Test2.class are not interfaces on the 2d parameter I want it to have a compile error since the 2d parameter must be an interface class
containsInterface(Test.class, Test.class);
containsInterface(Test.class, Test2.class);
acceptable use of my method
containsInterface(Test2.class, A.class);
containsInterface(Test.class, B.class);
what I tried
public static boolean containsInterface(Class clazz, Class<? extends Interface> intf)
I currently check if the class in the parameter is an interface then throw an exception. I would rather force people to not be able to call the method to begin with if it's not an interface
I am aware of Annotations and Enum objects are available to use as a class signature to make sure people are using the parameters right but, I can't seem to find the one for the interface itself.
I was told generics do not support interfaces or abstract classes type is this true even in jre 9-13+
You cannot force argument to be ANY interface implementation using type control system. The same would apply if you would like to eg force only Class<?> with abstract modifier. I am not sure if that is really needed as doing simple type isInterface assert is
Straigthforward
Clean
Robust
Easy to understand
Error prone
Testable
JDK Engineers does not care about that either. As an perfect example of such mechanism would be used (but there is none) is JDK Dynamic Proxy creation. You can create only create proxy of an interface (or set of) but not of class.
I don't think that it is just worth of the effort to write own preporocessors. Moreover it would be not universal - as you assume that runtime type must be know at compile time - what about dynamically loaded classes etc?
Intefaces in java has no super class that you can use in generic mode.
If you try get the super class of an interface with reflection returns null.
public static void main (String [] args) {
System.out.println(A.class.getSuperclass());
}
interface A {}
Output:
null
I have a utility class for interacting with the Datastore (GAE's in-built Datastore in my case) and it has methods like:
//Class GaeDataUtil
public static <T> Optional<Key<T>> saveEntity(T entity)
(Optional is from the Guava library and Key<T> from Objectify, although I doubt any of this makes a difference.)
I want my (minimal) hierarchy of entities to have a .save() method. So that for:
public class User extends RootEntity
where RootEntity provides:
public Optional<Key<T>> save() {
//Skipping the error-handling.
return GaeDataUtil.saveEntity(this);
}
I can write:
User myUser = new User();
// set some properties
Optional<Key<User>> optKey = myUser.save();
But of course that doesn't work because a call to myUser.save() returns Optional<Key<RootEntity>> not Optional<Key<User>> as I want.
I can avoid this issue by typecasting in User.save() (and Account.save() and Project.save() etc. etc.) and suppressing warnings, but even if there are only (say) 10 entity classes extending RootEntity, that's still a fair bit of boilerplate code to write just to typecast. Also, I think that much of the benefit of having a class hierarchy is lost if I have to write code (however minimal) for every derived class (there will be other, similar methods too).
Is there a better solution to this?
Update: using Java 7.
You will just need to type cast it to the Generic type T in the RootEntity.save() method.
public <T> Optional<Key<T>> save() {
//Skipping the error-handling.
return (Optional<Key<T>> GaeDataUtil.saveEntity(this); // This line will generate a warning.
}
And then when you write,
Optional<Key<User>> optKey = myUser.save();
It will automatically be inferred correctly because of Target Type Inference.
One solution is to parameterize RootEntity something like this:
class RootEntity<Subclass extends RootEntity> {
public Optional<Key<Subclass>> save() {...}
}
Then define your subclass like:
class User extends RootEntity<User> {...}
I've used this pattern before. If there is a slicker solution, I'll be eager to see it. :)
This is what finally worked:
public <T extends RootEntity> Optional<Key<T>> save1() {
#SuppressWarnings("unchecked")
Key<T> key = (Key<T>) ofy().save().entity(this).now();
return Optional.fromNullable(key);
}
Doing this in two steps works (get the Key, then wrap it up in an Optional) --- it let's the Target Type Inference work correctly. Doing it in a single step doesn't:
public <T extends RootEntity> Optional<Key<T>> save2() {
return (Optional<Key<T>>) Optional.fromNullable(ofy().save().entity(this).now());
}
This second form as suggested by #Codebender shows an error (Cannot cast from Optional<Key<RootEntity>> to Optional<Key<T>>), not a warning in Eclipse.
However, the basic idea by #Codebender of using Target Type Inference was sound.
Is something like that possible.
List<?> myList = getMyList();
class cls = class.forname("com.lab.myClass");
cls = myList.get(0);
cls.getValue();
Create an Instance with the fully-qualified name of a class and use their declared Methods?
No, if you call Class.forName, at compile time you know nothing about the returned Class instance. You don't even know that it represents a class; it might be an interface for example. In particular, if it is a class and you create an instance of it, you cannot call any methods of it except those which are already defined in Object because, at compile time, the compiler cannot check whether these methods exist.
The are two solutions:
First, you can use reflection to find out about the methods the class has, and to call these methods. This is very cumbersome.
Second, if you use Class.forName to dynamically load classes at runtime, often you know something about the classes you load. For example, you might know that the class implements a certain interface. Then you can cast the result of newInstance to this interface and then call the methods defined in this interface directly.
For example:
// in file Plugin.java
interface Plugin {
void doSomething();
}
// in file Main.java
public class Main {
...
void runPlugin() {
try {
Class<?> pluginClass = Class.forName("pkg.name.MyPlugin");
Plugin plugin = (Plugin) pluginClass.newInstance();
plugin.doSomething();
}
catch (...) {
// catch the necessary exceptions
}
}
}
At somewhere, that I can not remember, I read about an alternative way to instatiate a object:
Generally, we instantiate (and assign) this way:
User userObj = new User();
userObj.setId(1);
userObj.setName("Foo");
An alternative way could be:
User userObj = new User()
{{
setId(1);
setName("Foo");
}}
I was using this alternative, and it works.
1) Anyone knows what is it? Where is Java documentation link that metion about it?
I stop to use this because I was having problems with interfaces that ClassName implements, but the alternative way don't implements. Oo
public class User implements Serializable
{
private int id;
private String name;
//public Getters and Setters
}
2) When I try to serialize and use it (passing from one activity to another, using:
putExtra(String, Serializable)
it will throw NotSerializableException. Why?
Edit 1: An anonnymous class also implements the parent 'implementations', like Serializable from ClassName?
You are using anonymous class with initialization block. So it's just an equivalent to the:
SubClass extends ClassName{
{
classObj.setParam1(1);
classObj.setParam2(1);
}
}
new SubClass();
There is nothing wrong with this construction - but please notice that you are not creating object of ClassName class, but object of SubClass class.
As I said you are using anonymous class (class without name). This is bad - cause while serialization / deserialization JVM should exactly know what is the class of serialization data, so basically - don't use anonymous classes if you want to serialize them.
Ad 1.: This construct ist called "anonymous class".
Ad 2.: I bet your class contains a field which is not Serializable.
I have a Class object. I want to determine if the type that the Class object represents implements a specific interface. I was wondering how this could be achieved?
I have the following code. Basically what it does is gets an array of all the classes in a specified package. I then want to go through the array and add the Class objects that implement an interface to my map. Problem is the isInstance() takes an object as a parameter. I can't instantiate an interface. So I am kind of at a loss with this. Any ideas?
Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
if(clazz.isInstance(/*Some object*/)) //Need something in this if statement
{
retVal.put(clazz.getSimpleName(), clazz);
}
}
You should use isAssignableFrom:
if (YourInterface.class.isAssignableFrom(clazz)) {
...
}
you can use the below function to get all the implemented interfaces
Class[] intfs = clazz.getInterfaces();
You can use class.getInterfaces() and then check to see if the interface class is in there.
Class someInterface; // the interface you want to check for
Class x; //
Class[] interfaces = x.getInterfaces();
for (Class i : interfaces) {
if (i.toString().equals(someInterface.toString()) {
// if this is true, the class implements the interface you're looking for
}
}
You can also set the instance adding ".class"
Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
if(Interface.class.isAssignableFrom(clazz))
{
retVal.put(clazz.getSimpleName(), clazz);
}
}
A contribution for all the other answers, when possible do not use the most updated answer of method isAssignableFrom, even the "not great" answer of using clazz.getInterfaces() has better performance than isAssignableFrom.
A common mistake for developers when looking for an answer to the OP question, is to prefer isAssignableFrom when an instance is available, wrongly doing this:
if (IMyInterface.isAssignableFrom(myObject.getClass())) {
...
When possible, use IMyInterface.class.isInstance or instanceof as both of those have way better performance. Of course, as the OP stated; they have the drawback that you must have an instance and not just the class.
if (IMyInterface.class.isInstance(myObject)) {
...
if (myObject instanceof IMyInterface) { // +0.2% slower than `isInstance` (*see benchmark)
...
An even faster, but ugly solution would be to store an static Set with all the "valid" classes instead of checking them, this ugly solution is only preferred when you need to test classes a lot, as its performance outperforms all the other approaches for direct class check.
public static final Set<Class<?>> UGLY_SET = Stream.of(MyClass1.class, MyClass2.class, MyClass3.class).collect(Collectors.toCollection(HashSet::new));
if (UGLY_SET.contains(MyClass)) {
...
(*) JMH Benchmark for +0.2%
Please visit this answer from users #JBE, #Yura and #aleksandr-dubinsky, credits for them. Also, there's plenty of detail in that answer for the benchmark results to not be valid, so please take a look into it.