I have the following Java generics question
I have the following generic class thay may be sketched as:
public class MyClass<T> {
AnotherClass<T> another;
OtherClass<T> other;
...
}
where ... represents code that is not relevant to the case.
For the class MyClass<T> is not as important which exact type T is (as of now) but for both:
AnotherClass<T>
OtherClass<T>
is absolutely crucial what the generic type is and decisions will be made at runtime in base of that.
Based on that, the type T is not completely arbitrary, it may be either an instance of a hierarchy of classes T_1 or a hierarchy of classes T_2.
As is defined the class, the type T is equivalent to Object but I know that is equivalent to either T_1 or T_2
There is not businnes relation between entities T_1 and T_2 therefore I'm not doing:
public interface BaseT { ... }
public class T_1 implements BaseT { ... }
public class T_2 implements BaseT { ... }
public class MyClass<T extends BaseT>
Clarification about why using a generic if they are unrelated:
I'm defining (trying to) a generic class for both because even they are unrelated explictly, there is a implicit relation because both T_1 and T_2 can and will appear associated to the entity represented in MyClass
T will be the same for MyClass, AnotherClass and OtherClass so that in a instance there will only be either T_1 or T_2 but never both at the same time.
My question is, which alternatives do I have here other than design an
interface for MyClass and implement it for both T_1 and T_2?.
Can I achieve something like MyClass<T extends T_1 or T_2>?
Kind regards
Probably, this is not exactly what your're looking for, but you might give it a try:
Create an abstract generic class that implements everything:
public abstract class MyClass<T>
{
AnotherClass<T> another;
OtherClass<T> other;
// Add any code needed
}
Then create 2 generic classes for both base classes.
These classes may be empty if all code can be implemented in the abstract one:
public class MyT1Class<T extends T_1> extends MyClass<T>
{
}
public class MyT2Class<T extends T_2> extends MyClass<T>
{
}
I know it's not a very good answer but I couldn't leave it as a comment to the question.
You can check the type at runtime by trying the following:
public class MyClass<T>
{
// This factory-method creates an instance of the class if the correct type is passed
// It throws a RuntimeException if not.
public static <T> MyClass<T> getInstance(Class<T> type)
{
if (T_1.class.isAssignableFrom(type) || T_2.class.isAssignableFrom(type))
return (new MyClass<T>());
else
throw new RuntimeException("Cannot create instance of MyClass<" + type.getName() + ">");
}
...
}
Then
class T_3 extends T_2
{
}
....
MyClass<T_3> test_1;
test_1 = MyClass.getInstance(T_3.class); // This will succeed
MyClass<String> test_2;
test_2 = MyClass.getInstance(String.class); // Fails
Related
While sub classing from generic class type/Formal type parameter T/E with valid class type/Actual type parameter say e.g. Type/String there are many combinations occurs and that confusing which one to use and when?
public class SubClass<T> implements SuperIfc<T> <-- It is straight forward to understand
public class SubClass<T> implements SuperIfc<Type>
public class SubClass<Type> implements SuperIfc<T>
public class SubClass<Type> implements SuperIfc<Type>
public class SubClass<Type> implements SuperIfc
public class SubClass implements SuperIfc<Type>
public class SubClass implements SuperIfc<T> <--- Hope we cannot declare <T> in his case while initialising SubClass.
// Bounded type parameter
public class SubClass<T extends Type> implements SuperIfc<Type>
public class SubClass<T extends Type> implements SuperIfc<T> <-- Looks <T> at SuperIfc also refers <T extends Type>, and no need to declare it again at SuperIfc.
// Recursive type bound
public class SubClass<T extends Comparable<T>>> implements SuperIfc<T>
public class SubClass<T extends Comparable<T>>> implements SuperIfc<Type>
So that i can be more clearer on solving incompatible types while subclassing
Case_1:
public class Test {
interface TestIfc {
public static <T extends TestIfc> T of(int choice) {
if(choice == 1) {
return new TestImpl(); <-- PROB_1: incompatible type error
} else {
return new SomeOtherTestImpl(); //incompatible type error
}
}
}
static class TestImpl implements TestIfc {}
static class SomeOtherTestImpl<T extends TestIfc> implements TestIfc {
//The below method also having same error though with declaration
public T of() {
return new TestImpl(); <-- PROB_2: incompatible type error
}
}
}
Case_1: PROB_1: return type is T extends TestIfc and returned TestImpl implements TestIf So what is wrong?
Case_1: PROB_2: Similar to PROB_1, how to rectify without external casting. Please help.
Case_2:
public interface SuperIfc<T> {
public T create(Object label);
}
class Type {
public static Type of(){
return new Type();
}
}
------
public class SubClass<Type> implements SuperIfc<Type>{
#Override
public Type create() {
return Type.of(); <---- PROB_1: cannot resolve method
}
}
-------
public class SubClass<T extends Type> implements SuperIfc<Type>{
#Override
public Type create() {
return Type.of(); <---- PROB_1: is resolved
}
}
SuperIfc<Type> object = new SubClass(); <-- PROB_2 Unchecked assignement warning
SuperIfc<Type> object = new SubClass<TypeImpl>(); <-- PROB_3: bound should extend Type
I would like to know how to resolve Case_2, PROB_1 and PROB_2 together?
How to write subclass for generic super class with class types and what are the rules?
What should be taken care when changing generic T to class Type while subclassing? may be the difference between below and when to use?
public class SubClass<Type> implements SuperIfc<Type>
public class SubClass<Type> implements SuperIfc
public class SubClass implements SuperIfc<Type>
public class SubClass<T extends Type> implements SuperIfc<Type>
public class SubClass<T extends Type> implements SuperIfc<T>
public class SubClass<T> implements SuperIfc<Type>
In the first of() method, the method can return any type that implements InformationIfc, but your method always returns a specific implementation - InformationImpl - which is not acceptable.
For example, if you had some other class SomeOtherInformationImpl that implements that interface, the caller of that method would be allowed to write:
SomeOtherInformationImpl i = InformationImpl.of();
but your method doesn't return a SomeOtherInformationImpl.
The second of() method has the same issue as the first method.
If you instantiated your class with:
InformationImpl i = new InformationImpl<SomeOtherInformationImpl>();
the of() method would have to return a SomeOtherInformationImpl, not a InformationImpl.
Problems with case one.
PROB_1: return type is T extends TestIfc
Why do you have a generic here at all?. Since you have a static method I can do.
TestIfc broken = TestIfc<SomeOtherImplementation>.of(0);
SomeOtherImplementation is not a TestImpl. This is broken by design. What you really want is.
public static TestIfc of(int choice)
Next.
static class SomeOtherTestImpl<T extends TestIfc> implements TestIfc {
TestIfc is not parameterized, SomeOtherTestImp is, but it is completely unrelated to the interface you're implementing. Not to mention, TestIfc has a static method of that has nothing to do with the interface.
If I had to guess, I would think you want.
interface TestIfc<T>{}
static class TestImpl implements TestIfc<TestImpl> {}
static class SomeOtherTestImpl<T extends TestIfc> implements TestIfc<T>{}
That is the best I could come up with, because it is unclear what you actually want to happen.
Your examples for question 3
public class SubClass<Type> implements SuperIfc<Type>
This is broken, because SubClass<Type> declares Type to be the name of a generic parameter. It puts no restriction on the type, hence you get the method not found error.
public class SubClass<Type> implements SuperIfc
Broken, makes a generic parameter named Type, has nothing to do with your raw type version of SuperIfc
public SubClass implements SuperIfc<Type>
This is good.
public class SubClass<T extends Type> implements SuperIfc<Type>
public class SubClass<T> implements SuperIfc<Type>
These are both good, but the T has no relation to the SuperIfc parameter, hence your implementation would be.
public Type create(Object label);
The first generic parameter says the name you're going to use through the class.
This is a long answer, but please read through it (at least case 1 and the very end, you can skip over problem 2's solution in case 2 if you wish)
Case 1
Problem 1:
Your problem here is that the compiler cannot prove that T is the same as TestImpl or SomeOtherTestImpl. What if there was another class, call it TestFoo, that implemented TestIfc? Then, if you called the method as TestIfc.<TestFoo>of(1), you would expect an object of type TestFoo, but you would instead get a TestImpl, which is wrong. The compiler doesn't want you doing that, so it throws an error. What you should do is just remove the generics, like so:
public static TestImpl of(int choice) {
if(choice == 1) {
return new TestImpl();
} else {
return new SomeOtherTestImpl();
}
}
And then you can safely call TestIfc.of.
Problem 2:
This is basically the same thing. The compiler can't prove that the type parameter T of SomeOtherTestImpl is the same as TestImpl. What if you have an object like this (where TestFoo does not extend TestImpl but implements TestIfc)?
SomeOtherTestImpl<TestFoo> testImpl = ...;
And then you try to call the of method like this:
TestFoo testFoo = testImpl.of();
Can you see the problem here? Your of method returns a TestImpl, but you expect it to return a TestFoo because T is TestFoo. The compiler stops you from doing that. Again, you should just get rid of the generics:
public TestImpl of() {
return new TestImpl(); //This works now
}
Case 2
Problem 1
This problem is caused simply because you named your type parameter the same thing as your class - Type. When you changed the name of your type parameter to, say, T, it'll work because now Type is the name of a class. Before, your type parameter Type was hiding the class Type.
However, again, there is no need for a type parameter, since, you can just do this, and it'll satisfy all constraints.
public class SubClass implements SuperIfc<Type> {
#Override
public Type create() {
return Type.of();
}
}
Problem 2:
The unchecked assignment is because you didn't provide type arguments to SubClass when you did
SuperIfc<Type> object = new SubClass();
This can be fixed by either explicitly giving Type to SubClass:
SuperIfc<Type> object = new SubClass<Type>();
or by putting in an empty diamond (which I much prefer). This second approach means that the compiler can infer by itself that by new Subclass<>(), you mean new Subclass<Type>().
SuperIfc<Type> object = new SubClass<>();
Why the compiler complains:
That constructor call (new Subclass()) is basically like calling a method that looks like public SubClass makeNewSubClass() {...}. In fact, let's replace that statement above with this one, which will cause the same warning.
SuperIfc<Type> object = makeNewSubClass();
SubClass normally takes 1 type parameter (call it T), but here, it's not given any type parameters. That means that T could be anything, any class that extends Type (because of the constraint SubClass<T extends Type>).
You might thinking that if T is always going to be a subclass of Type, it should work all right, because the type of object above is SuperIfc<Type>. Assume there's a class like this - class TypeFoo extends Type - and that the method makeNewSubClass actually returns an object of type SubClass<TypeFoo> (new SubClass<TypeFoo>()).
Because of this, you expect object to be SuperIfc<Type> but it's actually SubClass<TypeFoo>. You probably think that that's all right, because after all, TypeFoo is a subclass of Type, right? Well, Java's generics are actually invariant, which means that for the compiler, SubClass<TypeFoo> is not a subclass of SuperIfc<Type> - it thinks they're 2 completely unrelated types. Don't ask me - I have no idea why :). Even SubClass<TypeFoo> isn't considered the same as or a subclass of SubClass<Type>!
That's why the compiler emits a warning - because raw types (that's what you call it when you have new SubClass() without giving type arguments) could represent anything. As for why it emits a warning and not an error - generics were introduced in Java 5, so for code before that to compile, the compiler lets you off with just a warning.
Problem 3:
According to the error, the type argument you gave (TypeImpl) should extend Type. This is because you defined SubClass as class SubClass<T extends Type> .... Here, you are giving TypeImpl as an argument for T, and so TypeImpl must extend Type, so all you need to do is put do class TypeImpl extends Type to solve that particular error.
However, even after you do that, you'll get an "incompatible types" error because, as I said earlier when talking about Problem 2, SuperIfc<Type> is not considered a supertype of SubClass<TypeImpl> even if TypeImpl extends Type.
You can do this
SuperIfc<TypeImpl> object = new SubClass<TypeImpl>();
or you can do this
SuperIfc<? extends Type> object = new SubClass<TypeImpl>();
In the second solution, we lose the information of what exactly T is in SuperIfc<T>; all we know is that it extends Type. The benefit of the second one is that you can later reassign any SubClass object to it (which doesn't work with the first version because it only allows SubClass<TypeImpl>:
SuperIfc<? extends Type> object = new SubClass<TypeImpl>();
object = new SubClass<Type>(); //works great
Alternative solution for Case 2
What it seems like you want to do is return objects of different type depending on type parameters. That's not really possible to do, since type parameters are erased at runtime. There are workarounds, though.
Here's one way to do it with a functional interface. It involves no casting and ensures type safety.
//This is the functional interface. You can also use Supplier here, of course
interface Constructor<T> {
T create();
}
class SubClass<T extends Type> implements SuperIfc<T> {
public Constructor<T> ctor;
public SubClass(Constructor<T> ctor) {
this.ctor = ctor;
}
#Override
public T create(Object label) {
return ctor.create();
}
}
class Type {}
class TypeImpl extends Type{}
By using a Constructor object, you will know that the returned Type object will always be of the right type. This is very easy to apply to your existing code - you don't need to write your own ConstructorImpl classes or anything.
You can now write this, and all you need to add is a method reference to the constructor (Type::new).
SuperIfc<Type> object1 = new SubClass<>(Type::new);
SuperIfc<? extends Type> object2 = new SubClass<>(TypeImpl::new);
With lambdas, you can also write this in a slightly more verbose way:
SuperIfc<TypeImpl> object = new SubClass<>(() -> new TypeImpl());
---
SuperIfc<? extends Type> object = new SubClass<>(() -> new TypeImpl());
I am following examples in "Effective Java" and came across the following code:
abstract static class Builder<T extends Builder<T>>
and its implementation:
public static class Builder extends Pizza.Builder<Builder>
Why is this declared T extends Builder<T> and not T extends Builder. Is it really needed to add the template <T>? What is the impact if I just use Builder<T extends Builder>?
It is called as "generic type". That declaration means T can be any type that is subclass of Builder<T>.
The goal of implementing Generics is finding bugs in compile-time other than in run-time. Finding bugs in compile-time can save time for debugging java program, because compile-time bugs are much easier to find and fix.
What is the impact if we just use Builder<T extends Builder>?
It transforms into raw type. And type safety goes off.
Builder<T extends Builder<T>> means that,
The class T passed in must implement the Builder interface / extend Builder class, and the generic parameter of Builder must be T itself.
I have some examples to show that actually the difference is not that big. I think the OP wants to know the difference between T extends Builder<T> and T extends Builder.
public abstract class Builder2<T extends Builder2> {
//doesn't compile either, because String is not a subtype of Builder2
static class WrongHouseBuilder extends Builder2<String> {}
//all ok
static class RawHouseBuilder extends Builder2 {}
static class HouseBuilder1 extends Builder2<RawHouseBuilder> {}
static class HouseBuilder2 extends Builder2<HouseBuilder1> {}
static class HouseBuilder3 extends Builder2<HouseBuilder2> {}}
Now with Builder<T>:
public abstract class Builder<T extends Builder<T>> {
//all ok
static class RawCarBuilder extends Builder {}
static class CarBuilder extends Builder<CarBuilder> {}
//ok as well, T doesn't have to be CarBuilder2
static class CarBuilder2 extends Builder<CarBuilder> {}
//doesn't compile because CarBuilder2 is not a subtype of Builder<CarBuilder2>
static class CarBuilder3 extends Builder<CarBuilder2> {}}
Of cause with T extends Builder<T>, you have more protection, but not that much.
UPDATE
Just to clarify, we should not use raw type. #Radiodef has provided an interesting example in the comment. And a quote from that answer to help you understand it:
In simpler terms, when a raw type is used, the constructors, instance methods and non-static fields are also erased.
Minor: It looks more natural to me to use Builder as an interface, not an abstract class. This is a sort of recursive type declaration. It is used for type safety to prevent nasty things like the following happens:
public abstract Builder<T extends Builder<T>> {
T build();
}
public class Entity extends Builder<String>{ // does not compile
#Override
public String build() {
return null;
}
}
public class Entity extends Builder<Entity>{ //ok
#Override
public Entity build() {
return null;
}
}
Anyway more naturally looking version (from my point of view) is:
public interface Buildable<T extends Buildable<T>> {
T build();
}
public final class Entity implements Buildable<Entity>{
//other methods
#Override
public Entity build() {
//implementation
}
}
I see that the question is about the <T> part in Builder<T>. Without this <T>, you simply get a raw type, and your IDE might complain.
But in my answer, I'd like to explain what's the purpose of T extends Builder<T>, because other answers do not seem to cover it (maybe you know this already).
T extends Builder<T> serves the purpose of returning appropriate Builder.this in all the Builder methods (except build() method, of course).
I usually use it with a protected abstract method like T thisInstance().
Example:
abstract class NamedBuilder<T extends NamedBuilder<T>> {
private String name;
T name(String name) {
this.name = name;
return thisInstance();
}
protected abstract T thisInstance();
}
final class MoreSpecificBuilder extends NamedBuilder<MoreSpecificBuilder> {
#Override
protected MoreSpecificBuilder thisInstance() {
return this;
}
}
Thanks to such approach, you do not have to redefine name() method in all the NamedBuilder subclasses to return the specific subclass.
Without such constraint type parameter T, you would have:
abstract class NamedBuilder {
NamedBuilder name(String name);
}
and you would need to override all such methods in subclasses like that:
final class MoreSpecificBuilder extends NamedBuilder {
#Override
MoreSpecificBuilder name(String name) {
super.name(name);
return this;
}
}
EDIT: Without the constraint extends Builder<T> on type parameter T:
abstract class NamedBuilder<T> {
// ...
}
this would work fine, although such design would be less intuitive and more error-prone.
Without such constraint, compiler would accept anything as T (e.g. String), so the constraint acts simply as a compile-time check for the implementors of NamedBuilder.
I want to know if is it possible to set a paramenter's type that is the type of the class that implements a given interface. Seeing some code the question will become more clear:
interface A {
A sum (???? another);
}
class AClass implements A {
private int internalStuff;
A public sum (???? another) {
// I want to access another.internalStuff in a type safe fashion
}
}
Of course I can substitute ???? with A type, and inside AClass.sum, cast it to AClass but that is ugly. Can "????" be replaced with some meaningful type declaration?
There is no self-type in Java, so you have to do a little trick to achieve this.
You can add a type parameter with a recursive type bound to the interface. The implementing class sets this parameter to its own type. Like this:
interface A<T extends A<T>> {
A sum (T another);
}
class AClass implements A<AClass> {
private int internalStuff;
public A sum(AClass another) {
// ....
}
}
There is nothing stopping AClass from doing implements A<SomeOtherAClass> though. You have to trust the implementing class to provide the correct type parameter.
I have interface:
interface Identifable<T extends Serializable> {
T getID();
}
and class that implement this:
public class Cat implements Identifable<Long> {
public Long getID(){...};
}
everything works fine. so far. Now I want to create GenericDAO, why I cannot create this?:
public abstract GenericDAO<T extends Identifable<S>> {
T getByID(S id);
}
I can only declare my GenericDAO as this:
public abstract GenericDAO<T extends Identifable, S> {
T getById(S id);
}
And complete class:
public CatDAO extends GenericDAO<Cat, Long> {
Cat getById(Long id);
}
But i think it's useless, because I repeat information. I already declared, that Cat implements Identifable< Long >, so why do I must declare GenericDAO< Cat, Long >, not just GenericDAO< Cat > ?
In Java, every generic type must be specified. You can go without specifying any type, but you can't go without specifying just one.
Also, every generic type must be specified in the declaration. If you want to have class GenericDAO<T extends Identifable<U>>, you must add the generic type declaration for U to your class declaration like this (since U is actually a generic type here):
public abstract class GenericDAO<T extends Identifable<U>, U>
The following is partially off-topic, but you might find it useful.
I've noticed that in your definition of GenericDAO two generic types are not tied to each other. This might not be what you want.
What you have here is a particular case in which the two generics are matching (the Long type in the Cat and CatDAO definitions). Consider having these declarations:
public class Dog implements Identifable<Long>
public class DogDAO extends GenericDao<Dog, String>
This would force you to write the getById method in DogDAO method:
Dog getById(String id);
Your getId method in the Dog returns a Long so your getById method int DogDAO would have to compare Strings to Longs. This is valid thing to do, but it's a bit counter-intuitive. Having a getById method for DogDAO that takes a Long parameter makes more sense, since the Dogs IDs are actually Longs.
If you want to tie the two types together, you can define the GenericDAO class as:
public abstract class GenericDAO<T extends Identifable<S>, S>
You still have to specify the second parameter, but at least the compiler can help you make sure that the types are matching.
Try this:
public abstract class GenericDAO<S extends Serializable, T extends Identifable<S>> {
abstract T getByID(S id);
}
Is it possible to narrow the type of a field in a Java class without making the containing class itself generic?
The generic example would be something like this:
abstract class MyClass {
//...
}
interface MyInterface {
//...
}
class MyConcreteClass<T extends MyClass & MyInterface> {
private T value;
}
Is there any way to do the following:
class MyConcreteClass {
private MyClass & MyInterface value;
}
This is essentially equivalent to MyConcreteClass or the raw MyConcreteClass type. In my implementation the type parameter will vary over the lifetime of the object (cursed mutability! It is imposed upon me by JPA!) and so the type annotation seems somewhat superfluous.
EDIT -
There is an additional restriction I forgot to mention. We will also have this:
class SubA extends MyClass
class SubB extends MyClass
class SubC extends MyClass
class SubSubA extends SubA implements MyInterface
class SubSubB extends SubB implements MyInterface
class SubSubC extends SubC implements MyInterface
Thus, simply declaring an abstract subclass of MyClass that implements MyInterface is not a suitable solution.
Also, the ultimate field type must be a concrete type, rather than simply an interface representing the intersection, for the simple reason that JPA-persisted entites cannot be referenced by their interface types. That is, a persistent field in a JPA entity class must be of either a primitive type or a concrete entity type.
I have never come across a problem like that (and thus no elegant solution comes to mind :-)... however...
interface Fooable
{
}
abstract class MyClass
implements Fooable
{
}
interface MyInterface
extends Fooable
{
}
class MyConcreteClass
{
private Fooable value;
}
In such complicated cases you should hide classes behind interfaces.
Then you can define an explicit interface for the intersection, i.e. an interface that extends both the interface corresponding to MyClass and MyInterface, and letting the appropriate superclasses implement it instead of MyInterface.
I don't think there is a way to do that. Not exactly like that anyway. However, since this is a private field and you control it entirely, you can just declare it as
private MyClass value;
but also make sure in all your code that only objects that implements MyInterface are affected to it, and cast everywhere you need to access it as the interface. Yes, it looks dirty, and it is (slightly).
You could also create the following derived class
abstract class MyDerivedClass extends MyClass implements MyInterface {
//...
}
and then use
private MyDerivedClass value;
This is much cleaner, but you have to create an other class, just for that purpose...