Constraints in interface implementation in java [duplicate] - java

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..){
}
}

Related

Check dynamically whether instance implements interface [duplicate]

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())

Generate lambda class for generic type variable using reflection

I am attempting to use Java interfaces as mixins in some high-level wrapper for type D.
interface WrapsD {
D getWrapped();
}
interface FeatureA extends WrapsD {
default ...
}
interface FeatureB extends WrapsD {
default ...
}
abstract class DWrapperFactory<T extends WrapsD> {
protected T doWrap(D d) {
return () -> d; // <- does not work
}
}
interface FeatureAB extends FeatureA, FeatureB {
}
class ProducingDWithFeatureAB extends DWrapperFactory<FeatureAB> {
protected FeatureAB doWrap(D d) {
return () -> d; // <- has to repeat this
}
}
As seen in ProducingDWithFeatureAB, doWrap has to be implemented in each sub-class even though the body is identical. (One more example of why Java generics is really broken.)
Since I already need to create concrete classes like ProducingDWithFeatureAB for other reasons and code exists in the JRE to sythesize lambda classes, it should be possible to write doWrap only once using reflection. I want to know how it can be done.
(doWrap used to be implemented using anonymous inner classes implementing the interface, which is even more biolderplate.)
This has nothing to do with generics; your generic example is just obfuscating the real issue.
Here's the core of the issue: lambda expressions need a target type that is a functional interface, and that target type must be statically known to the compiler. Your code doesn't provide that. For example, the following code would get the same error, for the same reason:
Object o = arg -> expr;
Here, Object is not a functional interface, and lambda expressions can only be used in a context whose type is a (compatible) functional interface.
The use of generics makes it more confusing (and I think you're also confusing yourself about how generics work), but ultimately this is going to be where this bottoms out.
The first thing you have to understand, is, that a method of the form
public Function<X,Y> fun() {
return arg -> expr;
}
is desugared to the equivalent of:
public Function<X,Y> fun() {
return DeclaringClass::lambda$fun$0;
}
private static Y lambda$fun$0(X arg) {
return expr;
}
whereas the types X and Y are derived from the functional signature of your target interface. While the actual instance of the functional interface is generated at runtime, you need a materialized target method to be executed, which is generated by the compiler.
You can generate instances of different interfaces for a single target method reflectively, but it still requires that all these functional interfaces have the same functional signature, e.g. mapping from X to Y, which reduces the usefulness of a dynamic solution.
In your case, where all target interfaces indeed have the same functional signature, it is possible, but I have to emphasize that the whole software design looks questionable to me.
For implementing the dynamic generation, we have to desugar the lambda expression as described above and add the captured variable d as an additional argument to the target method. Since your specific function has no arguments, it makes the captured d the sole method argument:
protected T doWrap(D d) {
Class<T> type=getActualT();
MethodHandles.Lookup l=MethodHandles.lookup();
try
{
MethodType fType = MethodType.methodType(D.class);
MethodType tType = fType.appendParameterTypes(D.class);
return type.cast(LambdaMetafactory.metafactory(l, "getWrapped",
tType.changeReturnType(type), fType,
l.findStatic(DWrapperFactory.class, "lambda$doWrap$0", tType), fType)
.getTarget().invoke(d));
}
catch(RuntimeException|Error t) { throw t; }
catch(Throwable t) { throw new IllegalStateException(t); }
}
private static D lambda$doWrap$0(D d) {
return d;
}
You have to implement the method getActualT() which ought to return the right class object, which is possible if the actual subclass of DWrapperFactory is a proper reifiable type, as you stated. Then, the method doWrap will dynamically generate a proper instance of T, invoking the desugared lambda expression’s method with the captured value of d—all assuming that the type T is indeed a functional interface, which cannot be proven at compile time.
Note that even at runtime, the LambdaMetafactory won’t check whether the invariants hold, you might get errors thrown at a later time if T isn’t a proper functional interface (and subclass of WrapsD).
Now compare to just repeating the method
protected SubtypeOfWrapsD doWrap(D d) {
return () -> d;
}
in each reifiable type that has to exist anyway…

java - Generic Return Type? [duplicate]

This question already has answers here:
Create instance of generic type in Java?
(29 answers)
Closed 8 years ago.
I'm not certain if this is possible in Java. Also, I'm not able to figure out what to query on Google for this.
Anyway, I want a method that takes as an argument a Class (interface or class) and the method's return type is an instance of that Class. I don't want to have to recast an Object after the fact.
I'm not certain if this feature exists or what the syntax would be. Let's say I have a class named XYZ and here is my pseudo method.
private XYZ createInstance(XYZ.class, other args) {
...
// create an instance of XYZ with other args named "_xyz_"
...
return _xyz_;
}
Now assume XYZ is some sort of generic syntax. Is this possible at all in Java? Thanks for any help.
private <T> T createInstance(Class<? extends T> c) {
return c.newInstance();
}
Use the diamond operator:
private <T> T createInstance(Class<T> concreteClass){
return concreteClass.newInstance();
}
//usage
Integer i = instanceWithThatMethod.createInstance(Integer.class);
To pass "arguments", you have to get the Constructor of the class matching the desired parameter types, and invoke the call on that one, like this:
private <T> T createInstance(Class<T> concreteClass, String stringArg){
return concreteClass.getConstructor(String.class).newInstance(stringArg);
}
//usage
SomeClass s = createInstance(SomeClass, "testString");
//equals
SomeClass s = new SomeClass("testString");
//where SomeClass HAS to serve:
public SomeClass(String s){
...
}

Get type name for generic parameter of generic class [duplicate]

This question already has answers here:
Get generic type of class at runtime
(30 answers)
Closed 4 years ago.
I have a small problem in java while using genericity. I have a class A :
public class A<T>
In a method of A, I need to get the type name of T.
Is there a way to find the string s using T ?
(If I create A<String> temp = new A<String>();, I want to be able to get java.lang.String at one point - I have to use genericity because one of my methods will have to return a List<T>).
This seems quite easy but I do not see how to do it.
You can't do this in general because of type erasure - an instance of A<String> doesn't know the type of T. If you need it, one way is to use a type literal:
public class A<T>
{
private final Class<T> clazz;
public A<T>(Class<T> clazz)
{
this.clazz = clazz;
}
// Use clazz in here
}
Then:
A<String> x = new A<String>(String.class);
It's ugly, but that's what type erasure does :(
An alternative is to use something like Guice's TypeLiteral. This works because the type argument used to specify a superclass isn't erased. So you can do:
A<String> a = new A<String>() {};
a now refers to a subclass of A<String>, so by getting a.getClass().getSuperClass() you can eventually get back to String. It's pretty horrible though.
You can get the name of the generics from the subclass. See this example.
We Define a parent class like this:
public class GetTypeParent<T> {
protected String getGenericName()
{
return ((Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]).getTypeName();
}
}
We then define its child class in this way:
public class GetTypeChild extends GetTypeParent<Integer> {
public static void main(String[] args) {
GetTypeChild getTypeChild = new GetTypeChild();
System.out.println(getTypeChild.getGenericName());
}
}
You can see that in the main method, or in any instance method, I am capable to get the name of the generics type, in this case the main will print: java.lang.Integer.
Short answer: Impossible.
Slightly longer answer: Once your code is compiled, the type parameters is discarded.
Thus, Java cannot know what you set there.
You could, however, pass the class in question to your object and operate on it:
public class Example<T> {
private final Class<T> clazz;
public Example(Class<T> clazz){
this.clazz = clazz;
}
...
}
As is normally the case, Apache has a solution for this one with TypeUtils:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/reflect/TypeUtils.html
A quick example from the above question:
TypeUtils.getTypeArguments(temp.getClass(), A.class).get(A.class.getTypeParameters()[0])
Disclaimer: I did not attempt building this first, but have used this utility in a similar fashion in the past.
Generics in Java are implemented by erasure, so no, you won't be able to get the name of the "type" which was used to create your generic collection at run-time. Also, why not just inspect the elements to know what type it belongs to?
If you're doing it in a subclass which has it's parent class defining the generic type, this is what worked for me:
// get generic type class name
String name = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0].toString();
// then when you've got the name, you can make the Class<T> object
Class.forName(name.replace("class ", ""))
Reason why I couldn't do it with #getClass() instead of #toString() in the first snip is that I was always getting the "Class" class, which is useless to me.

java: different return types when overloading

I have a class tree like this:
master class abstract class Cell
AvCell extends Cell
FCell extends Cell
i have an abstract method getValue() in Cell
Is it posibble to make the method getValue() to return int for AvCell and String for FCell?
Can i use generics for int String?
Thanks!
You could use generics and declare a Cell<T>.
Then just have getValue() return T
abstract class Cell<T> {
abstract T getValue();
}
Now:
class AvCell extends Cell<Integer> {
}
and
class FCell extends Cell<String> {
}
No. You can, however, narrow the return type when subclassing. This is known as "covariant return types". If a method in a base class returns T, you are allow to override that method in a subclass and have it return a subclass of T.
You can do the following:
abstract class Cell<T> {
public abstract T getValue();
}
class AvCell extends Cell<Integer> {
public Integer getValue() {
return 0;
}
}
class FCell extends Cell<String> {
public String getValue() {
return "foo";
}
}
Nope, no overloading on return types.
You could declare the return type to be Object and return either an Integer or a String, if you really want to.
You cannot do that normally. You have to have return types declared and the value being returned should be of the declared type or a subtype.
There are other ways to do that - declaring the method return type as Object and returning anything you want, but this is NOT the way to go.
First, a very simple question: Why do you want to return different types based on different input conditions? Generally this should be because you are doing two different things in the method based on the type you are passing. This is the place to look at. Have different methods for the different types and call one of them based on the type at hand. (And you can go further using factory patterns...)
If I understand the (changing) question correctly : No
From the Sun Java Tutorial:
Overloaded methods are differentiated by the number and the type of the arguments passed into the method. In the code sample, draw(String s) and draw(int i) are distinct and unique methods because they require different argument types.
You cannot declare more than one method with the same name and the same number and type of arguments, because the compiler cannot tell them apart. "
You can't overload the return type of a method. The JVM would not know which method to use, because the signatures are the same.
But, you could return Object, with one filling out Integer and the other String.
Yes, JVM actually allows it, so it can be done if you can generate byte codes correctly. The catch is you have to use a different tool other than javac. Here is a good tutorial: http://today.java.net/pub/a/today/2008/07/31/return-type-based-method-overloading.html
Why is it important? We built a library but want to change the return type from void to something else. Unfortunately, it required all applications depending on it to recompile. By manipulating bytes codes, the old applications can run without recompiling.

Categories

Resources