Check dynamically whether instance implements interface [duplicate] - java

This question already has answers here:
Test if object implements interface
(7 answers)
Closed 3 years ago.
I am trying to create a function which takes two parameters - a class instance and a interface - then returns true if the provided class instance implements the provided interface. My problem is that I cannot find a way to pass a interface as a parameter in this way.
My attempt currently looks something like this:
interface myInterface
{
}
class myClass implements myInterface
{
}
...
// Function to check if a class implements an interface:
boolean doesImplementInterface(object classToTest, ??? interfaceToTestAgainst)
{
if(i.getClass().isInterface())
{
return o.getClass().isInstance(i);
}
return false;
}
...
// Would call the "doesImplementInterface" method like this:
doesImplementInterface(new myClass(), myInterface);
It might be hard to see here, but when defining the "doesImplementInterface" function, I cannot figure out what type the second parameter must be. I am attempting to pass the interface that the provided class will be tested against, but as far as I can find, there is no variable type that I could use to pass a interface in this way.
Is passing a interface as a parameter in this way possible, or should I begin exploring alternative options?

Explanation
You need to pass the interface as Class (documentation) token. Also, you need to check the opposite way: interfaceToTestAgainst.isInstance(classToTest). Currently, you are trying to check whether the interface would be an instance of the class.
boolean doesImplementInterface(Object classToTest, Class<?> interfaceToTestAgainst) {
if (!interfaceToTestAgainst.isInterface()) {
return false;
}
return interfaceToTestAgainst.isInstance(classToTest);
}
or in one line:
boolean doesImplementInterface(Object classToTest, Class<?> interfaceToTestAgainst) {
return interfaceToTestAgainst.isInterface()
&& interfaceToTestAgainst.isInstance(classToTest);
}
Changed the naming a bit:
boolean isInstanceOfInterface(Object obj, Class<?> interfaceToken) {
return interfaceToken.isInterface()
&& interfaceToken.isInstance(obj);
}
A call of that method:
boolean result = isInstanceOfInterface(new Dog(), CanBark.class);
Note
Your question sounds like a XY problem. There might be way better solutions to solve what you are trying to solve with this attempt in the first place.
Losing type information, degrading the system to one which is not compile-time-safe anymore is generally very bad, if it can be avoided.
Consider re-thinking/-designing your approach. Just a note though, I do not know what you want to solve with that in the first place.

You do not need to create a method for this. Simple use
boolean doesImplement = ITest.class.isAssignableFrom(Test.class)
in case of instance, use instance.getClass() i.e.
boolean doesImplement = ITest.class.isAssignableForm(testObj.getClass())

Related

Approach doing the same stuff on different objects

I am currently making a library which is an utility for me to handle something which is not associated with the question (I am implicitly not saying the subject because it is not really important), however it does use reflection.
I am retrieving all declared and inherited methods from a class, which currently works fine and is not the issue. But the thing is, I need to do this as well for sub-classes since those inherit over like methods do (however you cannot override those like methods).
The problem that I am facing that it will use the same algorithm but there will be on difference, instead of calling clazz.getDeclaredMethods() I need to call clazz.getMethods. What is the best way too approach this, and I kind of need to return Class[] and Method[] in the method signature as well.
Normally I would look for a shared superclass, but in this case I prefer to the have Class[] and Method[] accordingly. For starters, I did some research and found some shared superclasses:
GenericDeclaration
AnnotatedElement
Since I need both Class[] and Method[] arrays I am thinking something
like generics, so the method would look like:
public static <T extends GenericDecleration> T[] getT () {
}
As mentioned by dasblinkenlight this will not work since the method doesn't take any arguments and cannot check whether to retrieve Class or Method objects.
But how would I detect whether I need to call getDeclaredMethods or getDeclaredClasses?
What is the best approach on how to do this without duplicating a lot of code? I really tried to explain myself here, but if it is still unclear what I am doing please feel free to ask away!
Thank you very much in advance!
After messing around with this, I have found a solution that totally fits my needs. This is a combination of generics and #dasblinkenlight's solution, like so:
public interface DeclExtractor<T extends GenericDecleration> {
public T[] extract (Class clazz);
public Class<? extends T[]) getGenericClass ();
DeclExtractor<Method> methodExtractor = new DeclExtractor<Method>() {
#Override
public Method[] extract (Class clazz) {
return clazz.getDeclaredMethods();
}
#Override
public Class<? extends Method[]> getGenericClass () {
return Method[].class;
}
}
// Same for Class
}
Now the method which also will return the correct type so you dont have to manually cast all GenericDeclaration to your original object type. My issue was that I used a collection for it and not the correct array:
public <T> T[] getAll (final DeclExtractor<T> extractor, Class<?> clazz) {
T[] declaration = extractor.extract (clazz);
//.. The algorithm..
// Return an instance of a collection as array (I use a set in my implementation)
final Object[] objects = myCollection.toArray();
return Arrays.copyOf(objects, objects.length, extractor.getGenericClass());
}
Technically you do not need the getGenericClass method in the interface, but I am using extract directly in a loop so I cannot pull the class of that, however, you can.
Hopefully this helps someone in the future :) Thanks again to #dasblinkenlight for the inspiration!
Your getT needs to get some input in order to decide what to do.
What about a method which can takes an enum as argument to determine whether it needs to get classes or methods? (from a comment)
There is a better approach: define an interface that performs the appropriate extraction, and make two instances of it - one for extracting classes, and one for extracting methods:
public interface DeclExtractor {
GenericDecleration[] extract(Class cl);
final DeclExtractor forClasses = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted classes
}
};
final DeclExtractor forMethods = new DeclExtractor() {
public GenericDecleration[] extract(Class cl) {
// make an array of GenericDecleration from extracted methods
}
};
}
Now you can rewrite your getT to take an "extractor", like this:
public static GenericDecleration[] getT (DeclExtractor extractor, Class cl) {
...
// When it's time to get components of the class, make this call:
GenericDecleration[] components = extractor.extract(cl);
...
}
To initiate a call to getT, pass DeclExtractor.forClasses or DeclExtractor.forMethods:
GenericDecleration[] c = getT(DeclExtractor.forClasses);
GenericDecleration[] m = getT(DeclExtractor.forMethods);

Is it possible to define a method that accepts any number of nested lists?

I have no particular use for this in mind, but is it possible to write a method that accepts any number of nested lists in Java?
I got as far as this:
private <T extends List<? extends T>> void masterOfLists(final T list) {
}
The small issue with this now is that it never ends. I neither want to lose generics, so simply accepting an Object and try casting it to a List every pass is not an option in my question.
I hoped it would be clear enough, but appereantly it isn't for some, I want the method masterOfLists to accept the following examples (and way more):
masterOfLists(new ArrayList<Object>())
masterOfLists(new ArrayList<List<Object>>())
masterOfLists(new ArrayList<List<List<Object>>>())
masterOfLists(new ArrayList<List<List<List<Object>>>>())
Instead of Object it may also be a concrete type like String.
The used List may be any type of list, like ArrayList or LinkedList or your custom implementation.
Using pure List won't help you here, you need to define a recursive class.
As an additional source of inspiration you can take a look at my code for Recursive Tic-Tac-Toe
You could create a class something like this:
public class Recursive<T> {
List<Recursive<T>> sub;
T value;
boolean hasSub() {
return sub != null;
}
T getValue() {
return value;
}
void forEach(Consumer<T> t) {
if (hasSub())
sub.forEach(t);
else t.accept(value);
}
}
You can use logic in this class to prevent it from both having a sub-list and an actual value, using constructors and/or setters.
And then if you want to iterate over it and print out all the sub-items recursively, you can use
Recursive<T> recursive;
recursive.forEach(System.out::println);
Then your method can look like this:
private <T> void masterOfLists(final Recursive<T> list) {
You won't get anywhere using pure Lists because the generic type of the list is not available at runtime, and the generics will only create a mess for you here. Using a recursive class is much easier.
The 'cheap' solution is to extend the ArrayList class with your own name, and force the Generics on the subclass. The SubClass is still an ArrayList....:
public class NestingList extends ArrayList<NestingList> {
// all we do is set the Generics...
}

call get methods for different classes behind one another

I have a class with name "ConstituentSet". it has one method namely "getNucleusInConstSet()" which the output will be from "Proposition" class . The new Class "Proposition" have another method namely "getProperty()". I want to know what is the Propertry of my "Proposition Nucleus" in class "ConstituentSet". but i do not know how can i do that.
I wrote as follow but It does not work. (ConstituentSet.getNucleusInConstSet()).getProperty())
public class ConstituentSet{
// Constructor
private Proposition nucleusInConstSet;
public Proposition getNucleusInConstSet() {
return nucleusInConstSet;
}
}
public class Proposition{
//Constructor
private Property property;
public Property getProperty() {
return this.type;
}
}
You have:
(ConstituentSet.getNucleusInConstSet()).getProperty()
But you need to call an instance of ConstituentSet
e.g.
ConstituentSet cs = new ConstituentSet();
cs.getNucleusInConstSet().getProperty();
Note that this idiom (chained method calls) can be a pain. If one of your methods returns null, it's difficult to understand which one it is (without using a debugger). Note also that invocations of the form a().b().c().d() are a subtle form of broken encapsulation (a reveals that it has a b, that reveals it has a c etc.)
if you type ((ConstituentSet.getNucleusInConstSet()).getProperty()) you are attempting to call a static method of ConstituentSet.
You need to instantiate it and then call on that object.
ConstituentSet anInstanceOf = new ConstituentSet();
anInstanceOf.getNucleusInConstSet()).getProperty());
This won't work:
ConstituentSet.getNucleusInConstSet().getProperty();
Because the getNucleusInConstSet() method is not static. You have to use an instance of ConstituentSet, something like this:
ConstituentSet cs = new ConstituentSet();
cs.getNucleusInConstSet().getProperty();
Of course, you have to make sure that nucleusInConstSet is not null, or you'll get a NullPointerException. Initialize its value in ConstituentSet's constructor or set it using setNucleusInConstSet().
Alternatively, you could make getNucleusInConstSet() static, but I don't think that's the right thing to do in this case (but we don't have enough information about the problem to say so).

check if item is instance of a generic class

public class Test<T>{
public boolean isMember(T item) {
if(item instanceof Test)
{
return true;
}
return false;
}
}
Is this the correct way to check if the item is an instance of the class?
I went through some searches and it seems that for a generic class, this will not work.
It's unclear what you're trying to test here, but here are a few possibilities:
Is item a T? Yes. Otherwise, it presumably couldn't be passed into the isMember method. The compiler would disallow it. (See Alex's caveat in the comments below.)
Is item a Test? Your isMember method as it is written would test this, but I'm sensing a code smell here. Why would you expect a T to also be a Test, but only some of the time? You may want to reconsider how you're organizing your classes. Also, if this is really what you want, then your method could be written as:
public boolean isMember(T item) {
return (item instanceof Test);
}
Which begs the question: why have a method like this in the first place? Which is easier to write?
if(obj instanceof Test) {...}
or
if(Test<Something>.isMember(obj)) {...}
I would argue that the first one is simpler, and most Java developers will understand what it means more readily than a custom method.
Is item a Test<T>? There is no way to know this at run time because Java implements generics using erasure. If this is what you want, you'll have to modify the method signature to be like Mike Myers's example.
T is not a variable, but a place holder for a class that is defined at runtime. Generics are a compile time feature, for that reason they add checks at compile time which may not have any meaning at runtime. We can only check the type of the object referenced at runtime which could be a super class type in the code. If we want to pass the type T as parameter to the method, all we have to do is to approach explicitly like the following:
void genericMethod(Class<T> tClass) {
if(String.class.isAssignableFrom(tClass))
or
void genericMethod(Class<T> tClass, T tArg) {
Note that the type might not be the same as here we can see how to manipulate:
genericMethod(Number.class, 1);
public class LinkList<T>{
public boolean isMemberOfClass(T item) {
if(item instanceof LinkList)
{
return true;
}
return false;
}
}
I'm sorry, I'm not suppost to post question as answer.
the class LinkList is a generic class.
the function is to check if the item belongs to the class. check if the have the same T.

Constraints in interface implementation in java [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java generics constraint require default constructor like C#
I want to set a constraint to type T that it must have a constructor without parameters. In C# it will be like:
public interface Interface<T> where T : new() { }
Is this feature available in Java?
Update: Is there some trick to make generic type T have a constructor?
You cannot define interface for constructors in Java. Nor you cann put any other constraints to type parameters, other than type variance.
Answering your updated question: only class can have a constructor in Java, T - is a type literal, it is not necessary has to be a class. During runtime using reflection you can check if your class is a ParameterizedType has a parameter that is actually a class and if it has an empty constructor.
You cannot do this at compile time in Java. I think that the best you can do is to try to verify this at runtime, by using reflection to do something like:
public static <T> boolean hasDefaultConstructor(Class<T> cls) {
Constructor[] constructors = cls.getConstructors();
for (Constructor constructor : constructors) {
if (constructor.getParameterTypes().length == 0) {
return true;
}
}
return false;
}
Then you can invoke this function by doing the following:
hasDefaultConstructor(String.class) => true;
hasDefaultConstructor(Integer.class) => false;
If this function returns false, then you know the class will have no default constructor, and you can throw an exception or whatever is appropriate for your application.
You could make T extend a class with the constructor you want
public interface Interface<T extends Constructable>{}
public abstract class Constructable{
public Constructable(params..){
}
}

Categories

Resources