implements vs extends in generics in Java - java

Can someone tell me what the differences between the first and second codes are?
MaxPQ stands for priority queue, which is a collection of "Key" objects that can be compared with each other.
Code 1:
public class MaxPQ<Key extends Comparable<Key>>{
...
}
Code 2:
public class MaxPQ<Key implements Comparable<Key>>{
...
}
The second code doesn't compile, but it is not intuitive to me why we need to extend instead of implement interfaces when using a generic.

The difference is pretty straightforward: second code snippet does not compile and never will. With generics you always use extends, for both classes and interfaces. Also super keyword can be used there, but it has different semantics.

There is no implements in generics. The second code is invalid. You probably confusing with :
public class MaxPQ implements Comparable<Key> {
...
}

I assume it was decided to use extends for both interfaces and classes, because in the case of generic class declaration it does not make any difference is type argument bound to interface or to class.
Of course meaning of extends is quite different from its typical usage in class definition. Angelika Langer do have nice text about different meanings of extends in Java: Does "extends" always mean "inheritance"?

Related

Java Enum can't extends other Enum, class can

User from Stackoverflow asked this question, unfortunately doesn't have answer which can explain situation.
Why enum can't extend another class while all other classes can
I have the same question. Java also tells that it is multyple extends and it is not supports. Java documentation.
But this part confusing me. If any class by default extends Object class(Main class in Java), and any new class can extend another class (except Object class), but any new Enum can't? Why?
Any Enum extends Enum class by default and for special for enum can't extend more classes, and if say it is program way, will be more understandable. But in documentation was writen can't extends because it is multyple classes. Maybe Documentation isn't correct? If someone can explain this part, please explain this.
Thank you!
As the comments on the question you linked to explain, all classes do not extend Object.
A class:
class Foo { }
implicitly extends Object, but a class:
class Bar extends Foo { }
Just extends Foo.
It is also a descendant of Object via Foo.
So an enum implicitly extends Enum, and can't extend anything else.
Enums are final classes, so nothing can extend them.
From the documentation you have linked:
Note: All enums implicitly extend java.lang.Enum. Because a class can
only extend one parent (see Declaring Classes), the Java language does
not support multiple inheritance of state (see Multiple Inheritance of
State, Implementation, and Type), and therefore an enum cannot extend
anything else.
Basically Enum has complier magic built in, that actually has the complier extend the Enum class from the java.lang.Enum.
Java doesn't support multiple inheritance of classes and hence you cant have extended Enums.
See this from the spec jls-8.9 as well.
An enum type is implicitly final unless it contains at least one enum
constant that has a class body.
It is a compile-time error to explicitly declare an enum type to be
final.

Get generic parameter of generic parameter during inheritance

Can, and if yes how, I access the generic parameter of another generic parameter, without also specifying it?
The example below is simplified from my current situation. All members and methods are omitted as they aren't relevant to the situation. LibraryRepository is a JPA/Spring-Type expecting an ENTITY and an ID.
abstract class AbstractEntity<ID> {}
class ConcreteEntity extends AbstractEntity<Long> {}
interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {}
//Desired declaration:
interface ConcreteRepository extends AbstractRepository<ConcreteEntity> {}
Without specifying Long on AbstractRepository, what to write instead of the two ?????, if that is at all possible?
For the sake of question-scope, please answer the question regarding generics, not how to implement spring-repositories in a better way. I'm glad for hints about that in the comments though.
interface AbstractRepository<ENTITY extends AbstractEntity<?????>> extends LibraryRepository<ENTITY, ?????> {}
One (particularly useful) way of thinking about generics is that they link types together. If you declare a new typevar and use it in only one place, because of erasure, that is effectively useless. Use it in two places and now you've told the compiler that the two places you used your T are linked: They can be anything, as long as they are the same thing.
This way of thinking also provides some insight here: Clearly you want your first ????? to be linked to your second ?????: For them to be equal.
The way to do that, then, is to declare a new typevar and use it:
interface AbstractRepository<ENTITY extends AbstractEntity<Q>, Q>
extends LibraryRepository<ENTITY, Q> {}
Unfortunately, that means AbstractRepository now gained a type variable, and I gather you didn't want that to happen.
Unfortunately, java has no way to link types without a type variable.
As a general rule of thumb, if you mix class hierarchies (things extending things implementing things), and lots of generics, you end up with looooots of generic parameters, and some of those will feel like DRY violations. The solution is to either accept it, or to not do one of those two things (Use composition over inheritance, or reduce the type variables you're using, or move them to methods instead), or to use a bunch of hacky reflection and 'warning-casts' (where you cast things to a typevar, which doesn't actually typecheck anything and tends to result in ClassCastExceptions in bizarre places: Places that don't even have a cast anywhere in the line, and not the place with the faulty code. Resulting in long and arduous bughunting exercises.
Maybe this is what you're trying to avoid, but I think you'd specify the generic parameter of your AbstractEntity as a parameter in AbstractRepository, something like this:
interface LibraryRepository<ENTITY, ID> {}
abstract class AbstractEntity<ID> {}
class ConcreteEntity extends AbstractEntity<Long> {}
interface AbstractRepository<ENTITY extends AbstractEntity<ID>, ID>
extends LibraryRepository<ENTITY, ID> {}
interface ConcreteRepository extends AbstractRepository<ConcreteEntity, Long> {}
I don't know how otherwise the compiler would be able to type-check the generic parameters for LibraryRepository.

Type Bounds with Comparable Interface in Java

In JDK 11 I'm creating a generic class called "Collection" such that whatever type is provided for the type parameter must implement the Comparable interface. The class declaration is currently as follows:
public class Collection <T extends Comparable<T>>
Originally I thought the class declaration should be this:
public class Collection <T implements Comparable<T>>
but JDK didn't like that.
So my question is why the class declaration is the former rather than the latter. Don't we extend classes and implement interfaces?
With respect to the syntax of bounds declaration, the language architects who added generics in Java 5 faced the following choice:
Mirror the declaration structure (with separate extends and implements bounds), or
Choose one form for upper-bounded types (e.g., T extends Foo, T <: Foo, etc.)
The latter was (sensibly, IMO) viewed as the more pragmatic choice, as at the point of declaring a type variable, whether the supertype happens to be a class or an interface is not material, and having a fussy syntax that required clients to use exactly the right keyword (and would have made compound bounds like <T extends ArrayList implements Serializable> even uglier) would likely be viewed as just making things harder to use with no actual benefit to either writers or readers of code.
Such decision often come about as a language is evolved, where strict consistency with precedent would only make things more difficult for no good benefit, and so language designers sometimes (after carefully considering the pros and cons of both alternatives) choose to break with precedent for the sake of a better result.
Collection is already in java.util. Creating another class with that name is going to confuse everybody; I suggest you pick something else.
Generics is about types in general. The word extends is used, and this kinda mirrors the same use of that keyword in, for example, class Foo extends Bar, but it's not quite the same meaning. The point is, the spec says it is extends and not implements regardless of what comes after, and there's not much point in going any further than 'spec says so' on this one.
Would you therefore want implements E or extends E, given that E may be a class or an interface? Unless you want a third keyword (possibly context-sensitive) then it doesn't make sense to distinguish.

Understanding java recursive generic type definitions with type erasion

I'm very confused facing this line of code:
public abstract class ClassName<T extends ClassName<?>>{}
I know what <T> is, what abstract is, what inheritance is but I just can't summarize all I see in this line.
Please can someone explain in simple words what does that interesting thing means?
Not a duplicate of questions about <T> and <?>. The confusing thing here is that ClasName appears twice.
Thanks in advance.
public means the class is visible to all other classes.
abstract means the class can not be instantiated (you'll have to find a non-abstract subclass for that)
inheritance is an important concept in object-oriented programming. Read a book about OOP or consult wikipedia.
T extends ClassName<?> means there is an upper bound put on the type parameter T, such that T needs to be a subclass of ClassName<?>. ? means unbounded type parameter.
I will provide a little more meaningful example that might make it easier to understand the concept of using bounded recursive type parameters. Lets assume you have a class Thingy. You want all subclasses of Thingy to be comparable, but just to the same subclass. Ie you want nails to be comparable to nails, but not bikes:
interface Thingy<T extends Thingy<T>> extends Comparable<T> {}
class Nail implements Thingy<Nail> {
#Override public int compareTo(Nail o) { ... }
}
class Bike implements Thingy<Bike> {
#Override public int compareTo(Bike o) { ... }
}
So ClassName has a generic parameter T and this parameter needs to fit a certain requirement, in this case extends a certain type S, that means, T must inherit S. Now the interesting thing in this case is this S.
We have S to be ClassName<?>, so T must inherit from ClassName with a wildcard. For the wildcard aka the question mark please have a look at the link Michael Markidis gave in a comment to your question.
The real fun now is that this definition
public abstract class ClassName<T extends ClassName<?>>
allows recursive generic type defintion. So you could have something like
ClassName<ClassName<ClassName<ClassName<?>>>> test;
for whatever that's worth :)
EDIT: Given
ClassName2<T extends ClassName<?>> extends ClassName<T>
thats relatively easy in comparison. We want to inherit ClassName but not "destroy" the generic argument, so we take one ClassName would accept, in this case T extends ClassName<?>. In extends ClassName<T> the compiler checks if this (i.e. ClassName2's) T fits the T of ClassName, which was the requirement (remember ClassName's definition) T extends ClassName<?>, so this obviously works.
In addition, we have ClassName2<?> extending ClassName<?>, so now you can mix the two types however you want:
ClassName2<ClassName<ClassName<ClassName<?>>>> test2;
ClassName2<ClassName<ClassName2<ClassName<?>>>> test3;
However, if you would have, say
class ClassName3<T extends ClassName3<?>> extends ClassName<T>
(the public and abstrac modifiers don't really influence the generic behavior here), you can only have things like
ClassName3<ClassName3<ClassName3<ClassName3<?>>>> test4;
ClassName2<ClassName<ClassName3<ClassName3<?>>>> test5;
since ClassName and ClassName2don't inherit ClassName3.

Generics in Java with and abstract class

I was reading some code for learn something about manage data in Android.
When i read a litle of the code...
I find this declaration.
public abstract class DBObject<T extends DBObject<?>> implements Cloneable{}
I understadn that this is and Abstract class with T that is a Generic Object
but i don't understand why y have to put a wildcart after Extend the same class.
Here is all the code
https://github.com/tasks/tasks/blob/master/src/main/java/com/todoroo/andlib/sql/DBObject.java
It looks like this is used so that it can be parameterised with its subclasses. It would be used like so:
class Foo extends DBObject<Foo> { ... }
It appears this is done solely so that the as() method will return the correct type.
The reason for the wildcard is because without it you would have to somehow specify a recursive generic definition, DBObject<T extends DBObject<T extends DBObject<...>>> - which is impossible.
Edit: Although see comments below; the wildcard is not actually necessary.

Categories

Resources