Java Generics & operator - java

I am facing some difficulty to understand an expression in java generics.
Please help on this:
public interface Inter {
<T extends Enum<T> & FunctionalInterface> String getString();
}

The code you have given is legal, but useless.
It is useless for two reasons:
You have defined a generic type, T, as part of the method declaration that must implement the Enum<T> interface as well as the FunctionalInterface interface. However you haven't then used that type anywhere in the method's signature (i.e. arguments or return type) so it is effectively ignored.
Having an interface implement 'FunctionalInterface' is possible, but certainly not it's intended use. It is designed to be an annotation to an interface, not an interface itself.
You could make this combination work:
public interface Inter {
<T extends Enum<T> & FunctionalInterface> String getString(T value);
}
static class InterImpl implements Inter {
#Override
public <T extends Enum<T> & FunctionalInterface> String getString(T value) {
return value.name();
}
}
enum EnumImpl implements FunctionalInterface {
A, B, C;
#Override
public Class<? extends Annotation> annotationType() {
return null;
}
}
public static void main(String[] args) {
InterImpl impl = new InterImpl();
System.out.println(impl.getString(EnumImpl.B));
}
You'll see that the EnumImpl enumeration implemements Enum and FunctionalInterface so it can be used as an argument to getString.
So that's an explanation but, frankly, I can't think of any useful use case for such a piece of code.

Related

java generics: Bound mismatch for string

my code is as below, and I got the error message Bound Mismatch Error: The type String is not a valid substitute for the bounded parameter <K extends myComparable<K>> of the type myInterface<K,V>:
interface myComparable<T> {
public int compareTo(T o);
}
interface myInterface<K extends myComparable<K>, V> {
}
public class myClass implements myInterface<String,String>{
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
However, if I changed K extends myComparable<K> to K extends Comparable<K> (without changing the first line; i.e. to use Comparable instead of myComparable), the error will be solved.
Why? And how can I use my own myComparable?
I finally got a solution (i.e. to use myString instead of String):
interface myComparable<T> {
public int compareTo(T o);
}
interface myInterface<K extends myComparable<K>, V> {
}
class myString implements myComparable<myString>{
#Override
public int compareTo(myString o) {
return 0;
}
}
public class myClass implements myInterface<myString,myString>{
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
When you write implements myInterface<String, String>, you're 'binding' the K type variable to String and the V type variable to String.
The declaration of the K type variable in particular has a bound on it: You've declared it as myInterface<K extends myComparable<K>, V> which means that any bound you pick for K must at least 'fit' this restriction.
And it doesn't, which is why the compiler won't let you.
The java.lang.String class actually implements Comparable<String> - it's right there in the javadoc as well as the source if you care to look; you can also just cast it:
Comparable<String> test = "hello"; // this compiles and runs fine.
The reason is that string was written by sun/oracle as: public final class String implements Comparable<String>.
It was not written with implements myComparable<String>.
It is not possible to make java.lang.String implement your interface.
That is not how interfaces work; java is nominally and not structurally typed: You can't decree that all Strings are myComparables, just because they so happen to have a compareTo method.
Imagine it worked that way and I wrote this class:
public class Gun {
public void shoot(Person person) { ... }
}
quite a dangerous class!
Let's say it worked the way you appear things are. Then I could do:
public interface Camera {
public void shoot(Person p);
}
Camera c = new Gun();
c.shoot(somebody);
and good grief, now we have an extremely dangerous situation going on. Fortunately, java does not work this way; A Gun is not a Camera. Eventhough it so happens to have all the methods that the Camera interface declared.
You can make your own types that implement your own interfaces, of course. That's no problem. However, in general, it doesn't seem useful to make an interface named myComparable.

java generic related to type inference

I'm a java newbie, and I have some codes like below.
public interface TestJava<T extends MyClass, U> {
public U func(T t);
}
The problem is that U is totally dependant on T so that if T is determined, U is also determined (declaring U is unnecessary!). As an example, if T is String, then U must be Integer and cannot be others. In C++, U can be easily removed using the keyword typedef like below if T is a user-defined class.
class UserDefinedClass {
public:
typedef int ReturnType;
};
template<class T> class TestCpp {
T::ReturnType func(T t);
};
However, java doen't have such keyword (as far as I know), so I have no idea how to achieve this.
Note that T in the java code is a user-defined object, not String, Integer or others.
Don't get confused with the example :)
One thing you could do is hide the eyesore by extending the interface and then from then on just call the extended interface. The point here is that you don't have to pass in the second type if you are SURE it will always be (eg: Integer*) the same.
public class MyClass{
boolean truth;
}
public interface Lame{
}
public interface TestJava<T extends MyClass, U> {
public U func(T t);
}
public interface TestJavaMore<T extends MyClass> extends Lame{
public void funky();
}
public interface TestJavaEvenMore<T extends MyClass> extends TestJava<T, Integer> {
}
Another solution which I think I would recommend if you have more than one combination of types for T and U is to use a factory to create a concrete instance with the types you want. This is a common pattern you can research, but in this case, it's something like:
public class TestJavaImpl<T extends MyClass, U> implements TestJava{
#Override
public Object func(MyClass t) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
public TestJava TestJavaFactory(){
TestJava testJava = null;
if (true == true){
testJava = new TestJavaImpl<MyClass, Integer>();
} else {
testJava = new TestJavaImpl<MyClass, Float>();
}
return testJava;
}
*Tip:Remember too w/ java and templates you have to use "I"nteger not "i"nteger

Restrict generic types in java based on implementation of generic interface

So I have got 2 generic interfaces.
First interface is implemented like this.
public interface First<E>
{
void method(E e)
}
public class FirstImpl implements First<String>
{
void method(String s) { System.out.println(s); }
}
public class FirstImpl2 implements First<Double>
{
void method(Double d) { System.out.println(d); }
}
I need the second interface's (second interface is shown below) generic type to allow only the classes that are used when implementing the first interface, in our case String and Double. Is there any clean way to do this, something like
public interface Second <E, ? extends First<E>>
{
void method(E e);
}
public class SecondImpl <E> implements Second <E, ? extends First<E>>
{
void method(E e) { System.out.println(e); }
}
, so the in Second's generic E would fit only String and Double and all classes that are used to implement First<E>?
Nope. You can not restrict the generic type of the Second in that sense. You can still provide an another type information independently. Say,
class XYZ implements First<Bar> { ... }
an another class may provide an another type information for the Second, like
class ZYX implements Second<Foo, SomeOtherType<Foo>> { ... }
assuming SomeOtherType implements/extends whatever from type First. If you want to bind those two interfaces on their generic type, you can use inheritance between the implementations:
interface First<T> {}
interface Second<T> {}
class Foo<E extends T> implements First<T> {}
class Bar<E extends T> extends Foo<E> implements Second<E> {}
Now, the type E, is associated with the type T, via E extends T.

Java Enum as generic type in Enum

I'm trying to create an abstract method in a abstract class that takes my own Enum as argument. But I want also that that Enum will be generic.
So I declared it like that:
public abstract <T extends Enum<T>> void test(Enum<T> command);
In the implementation, I have en enum as that one:
public enum PerspectiveCommands {
PERSPECTIVE
}
and the method declaration becomes:
#Override
public <PerspectiveCommands extends Enum<PerspectiveCommands>> void test(Enum<PerspectiveCommands> command) {
}
But if I do:
#Override
public <PerspectiveCommands extends Enum<PerspectiveCommands>> void test(Enum<PerspectiveCommands> command) {
if(command == PerspectiveCommands.PERSPECTIVE){
//do something
}
}
I don't have access to the PerspectiveCommands.PERSPECTIVE with the error:
cannot find symbol symbol: variable PERSPECTIVE location: class Enum<PerspectiveCommands> where PerspectiveCommands is a type-variable: PerspectiveCommands extends Enum<PerspectiveCommands> declared in method <PerspectiveCommands>test(Enum<PerspectiveCommands>)
I've made a workaround like this:
public <T extends Enum<T>> byte[] executeCommand(Enum<T> command) throws Exception{
return executeCommand(command.name());
}
#Override
protected byte[] executeCommand(String e) throws Exception{
switch(PerspectiveCommands.valueOf(e)){
case PERSPECTIVE:
return executeCommand(getPerspectiveCommandArray());
default:
return null;
}
}
But I would like to know if it's possible to not pass by my workaround?
In your method implementation PerspectiveCommands is not the enum but your type parameter, which often is called T. It thus shadows the enum of the same name like axtavt already said, thus PERSPECTIVE is unknown here.
Your abstract method declaration is fine but you might use a slightly different approach.
public void test(PerspectiveCommands command) would not work, since this method would not override the generic version. The reason is that with the generic version the type is inferred from the parameter and thus you could pass any enum.
However, I assume you have an interface or abstract class which defines the abstract method. So try something like this:
interface TestInterface<T extends Enum<T>>
{
public abstract void test(T command);
}
class TestImpl implements TestInterface<PerspectiveCommands>
{
#Override
public void test(PerspectiveCommands command) {
if(command == PerspectiveCommands.PERSPECTIVE){
//do something
}
}
}
#mike's answer is the way to go.
public interface Command1 {
}
public enum MyCommand1 implements Command1 {
}
abstract <E extends Enum<E> & Command1> void execute(E command);
Here comes an another version
// intending to be used only on enums
public interface Command2<E extends Enum<E>> extends Command1 {
}
public enum MyCommand2 implements Command2<MyCommand2> {
}
abstract <E extends Enum<E> & Command2<E>> execute(E command);
As #axtavt already pointed out, the problem is the shadowing.
If you want your code to work as it is, you could change the name of the type variable to remove the shadowing.
public <C extends Enum<C>> void test(Enum<C> command)
I would also add an interface to the type boundary to just allow command enums and not an instance of every enum derived class.
public <C extends Enum<C> & CommandInterface> void test(Enum<C> command)

Declare attribute of type that extends 2 different interfaces

I would like to declare attribute that holds instance of class that implements 2 different interfaces. I have tried this syntax:
private <? extends Interface1 & Interface2> name;
and this:
private <T extends Interface1 & Interface2> T name;
None of those work. Is it possible? What's the syntax? I'm trying to avoid declaring another interface that inherits from both Interface1 and Interface2.
Edit:
The class containing this attribute should not have any type arguments. That is nothing like this:
public class MyClass<T extends Interface1 & Interface2>{
private T name;
...
}
It would not make any sense for those using the class. It is not expected neither logical not possible for that class to be generic.
That needs to go in the class declaration, such as:
public class TestG<T extends Cloneable & Serializable> {
private T name;
}
One alternative is to set it in a method (but not a variable)
public class TestG {
public <T extends Cloneable & Serializable> void method(T parameter) {
}
}
A variable cannot be generic.
private <T> T var;
is not possible - at which point is T defined? When accessing var, I cannot make much assumptions on what I used at assignment time.
Java allows generics on classes and on methods. So you can have
private <T implements Cloneable & Serializable> void setVar(T val);
and you can have a class-wide type T.
But always remember that in the end, it is implemented by type erasure. You can always emulate more complex logic using getters, setters and casts. When done properly, it will give you just as much type safety.
The simplest way to obtain a variable with the type safety you want is to just use two variables, and a setter to keep them in sync.
private Serializable vars;
private Cloneable vars;
will of course give you a good type safety. But yes, it needs 4 bytes of additional memory, and a setter.
Here's the casting approach you asked:
private Object internal_var;
// Implementation notice: do not remove this generic.
// Due to a Java limitation, we *do* want these two constraints!
public <T extends Serializable & Cloneable> void setVar(T val) {
internal_var = val;
}
public Serializable getSerializable() {
return (Serializable) internal_var; // Type checked in setter!
}
public Cloneable getCloneable() {
return (Cloneable) internal_var; // Type checked in setter!
}
// This is the way to use it in a generic getter:
public <T extends Serializable & Cloneable> T getVar(Class<? super T> cls) {
return (T) cls.cast(val);
}
Note that in order to use T in the getter, we do need to have a parameter involving T.
Assuming we know a class Example implements Serializable, Cloneable, we can then use
// This actually ensures we get an instance of `Example` out:
Example e = instance.getVar(Example.class);
You can declare that type parameter in your class declaration, or method declaration, if that is a local variable, and use that type instead: -
public class Demo<T extends Interface1 & Interface2> {
private T t;
}
or: -
public class Demo {
public <S extends Interface1 & Interface2> void demo(S param1) {
S param;
}
}
If i understand your question correctly, you want a generic class which implements both the inetrfaces.
declare a generic type argument in your class definition and make it as an instace variable type.
public class Implementor<T extends Interface1<T> & Interface2<T>> {
private T t;
}
EDIT:
you cannot declare a type argument at instance variable declaration like
private <T extends I1 &I2> T t; //this cant be achieved.
at method level though is possible.
public <T extends I1 & I2> void method(T t){
}

Categories