Java Generics, is C equal to T ?
No, there is no significance.
There are conventions (see Java Generics Tutorial):
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S, U, V etc. - 2nd, 3rd, 4th types
Difference between ? super T and ? extends T in Java
extends
The wildcard declaration of List<? extends Number> foo3
means that any of these are legal assignments:
List<? extends Number> foo3 = new ArrayList<Number>(); // Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>(); // Double extends Number
Reading - Given the above possible assignments, what type of object are you guaranteed to read from
List foo3
:- You can read a
Number
because any of the lists that could be assigned tofoo3
contain aNumber
or a subclass ofNumber
. - You can't read an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't read a
Double
becausefoo3
could be pointing at aList<Integer>
.
- You can read a
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can't add an
Integer
becausefoo3
could be pointing at aList<Double>
. - You can't add a
Double
becausefoo3
could be pointing at aList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at aList<Integer>
.
- You can't add an
You can't add any object to List<? extends T>
because you can't guarantee what kind of List
it is really pointing to, so you can't guarantee that the object is allowed in that List
. The only "guarantee" is that you can only read from it and you'll get a T
or subclass of T
.
super
Now consider List <? super T>
.
The wildcard declaration of List<? super Integer> foo3
means that any of these are legal assignments:
List<? super Integer> foo3 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>(); // Object is a superclass of Integer
Reading - Given the above possible assignments, what type of object are you guaranteed to receive when you read from
List foo3
:- You aren't guaranteed an
Integer
becausefoo3
could be pointing at aList<Number>
orList<Object>
. - You aren't guaranteed a
Number
becausefoo3
could be pointing at aList<Object>
. - The only guarantee is that you will get an instance of an
Object
or subclass ofObject
(but you don't know what subclass).
- You aren't guaranteed an
Writing - Given the above possible assignments, what type of object could you add to
List foo3
that would be legal for all the above possibleArrayList
assignments:- You can add an
Integer
because anInteger
is allowed in any of above lists. - You can add an instance of a subclass of
Integer
because an instance of a subclass ofInteger
is allowed in any of the above lists. - You can't add a
Double
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add a
Number
becausefoo3
could be pointing at anArrayList<Integer>
. - You can't add an
Object
becausefoo3
could be pointing at anArrayList<Integer>
.
- You can add an
PECS
Remember PECS: "Producer Extends, Consumer Super".
"Producer Extends" - If you need a
List
to produceT
values (you want to readT
s from the list), you need to declare it with? extends T
, e.g.List<? extends Integer>
. But you cannot add to this list."Consumer Super" - If you need a
List
to consumeT
values (you want to writeT
s into the list), you need to declare it with? super T
, e.g.List<? super Integer>
. But there are no guarantees what type of object you may read from this list.If you need to both read from and write to a list, you need to declare it exactly with no wildcards, e.g.
List<Integer>
.
Example
Note this example from the Java Generics FAQ. Note how the source list src
(the producing list) uses extends
, and the destination list dest
(the consuming list) uses super
:
public class Collections {
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
for (int i = 0; i < src.size(); i++)
dest.set(i, src.get(i));
}
}
Also see
How can I add to List<? extends Number> data structures?
How to use Class T in Java?
Using the generified version of class Class allows you, among other things, to write things like
Class<? extends Collection> someCollectionClass = someMethod();
and then you can be sure that the Class object you receive extends Collection
, and an instance of this class will be (at least) a Collection.
What does T : new() mean with generics?
new()
mean that T
must have default(parameterless) ctor.
Constraints on Type Parameters (C# Programming Guide)
Java generics variable T value
With the two answers from codebender and nicolas filotto i was able to do it.
I had to remove the setValue method to put it outside the class. So here is the complete class:
public class FilterExpression<T extends Comparable<T>> {
public static final Integer BEGINS_WITH = 0;
public static final Integer ENDS_WITH = 1;
public static final Integer CONTAINS = 2;
public static final Integer EQUAL = 3;
public static final Integer NOT_EQUAL = 4;
public static final Integer GREATER_THAN = 5;
public static final Integer GREATER_EQUAL_THAN = 6;
public static final Integer LESS_THAN = 7;
public static final Integer LESS_EQUAL_THAN = 8;
private static final Map<String, Integer> OPERATOR_MAPPING;
static {
Map<String, Integer> temp = new HashMap<>();
temp.put("bw", BEGINS_WITH);
temp.put("ew", ENDS_WITH);
temp.put("ct", CONTAINS);
temp.put("eq", EQUAL);
temp.put("nq", NOT_EQUAL);
temp.put("gt", GREATER_THAN);
temp.put("gq", GREATER_EQUAL_THAN);
temp.put("lt", LESS_THAN);
temp.put("lq", LESS_EQUAL_THAN);
OPERATOR_MAPPING = Collections.unmodifiableMap(temp);
}
private String field;
private Integer operator;
private T value;
public FilterExpression(String field, String operator, T value) {
this.field = field;
setOperator(operator);
this.value = value;
}
public Boolean validate() {
if (StringUtils.isEmpty(field) || operator == null || value == null) {
return false;
}
Class c = value.getClass();
if (c == String.class) {
return operator >= BEGINS_WITH && operator <= NOT_EQUAL;
} else if (c == Integer.class || c == Float.class || c == Double.class || c == Date.class) {
return (EQUAL >= EQUAL && operator <= LESS_EQUAL_THAN);
} else if (c == Boolean.class) {
return operator == EQUAL || operator == NOT_EQUAL;
} else if (c == Identification.Type.class) {
return operator == EQUAL || operator == NOT_EQUAL;
}
return false;
}
public String getField() {
return field;
}
public void setField(String field) {
this.field = field;
}
public Integer getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = OPERATOR_MAPPING.get(operator.toLowerCase());
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
public <R> Predicate toPredicate(CriteriaBuilder cb, Root<R> root) {
if (Objects.equals(operator, FilterExpression.EQUAL)) {
return cb.equal(root.<T>get(field), value);
} else if (Objects.equals(operator, FilterExpression.NOT_EQUAL)) {
return cb.notEqual(root.<T>get(field), value);
} else if (Objects.equals(operator, FilterExpression.CONTAINS)) {
return cb.like(root.<String>get(field), "%" + value + "%");
} else if (Objects.equals(operator, FilterExpression.ENDS_WITH)) {
return cb.like(root.<String>get(field), "%" + value);
} else if (Objects.equals(operator, FilterExpression.BEGINS_WITH)) {
return cb.like(root.<String>get(field), value + "%");
} else if (Objects.equals(operator, FilterExpression.GREATER_THAN)) {
return cb.greaterThan(root.<T>get(field), (T) value);
} else if (Objects.equals(operator, FilterExpression.GREATER_EQUAL_THAN)) {
return cb.greaterThanOrEqualTo(root.<T>get(field), (T) value);
} else if (Objects.equals(operator, FilterExpression.LESS_THAN)) {
return cb.lessThan(root.<T>get(field), (T) value);
} else if (Objects.equals(operator, FilterExpression.LESS_EQUAL_THAN)) {
return cb.lessThanOrEqualTo(root.<T>get(field), (T) value);
}
return null;
}
}
typescript generic type with equal operator means?
If you don't provide a type Data
(which must extend DataType
), it will default to DataType
.
From previous release notes
Consider a function that creates a new HTMLElement, calling it with no arguments generates a Div; you can optionally pass a list of children as well. Previously you would have to define it as:
declare function create(): Container<HTMLDivElement, HTMLDivElement[]>;
declare function create<T extends HTMLElement>(element: T): Container<T, T[]>;
declare function create<T extends HTMLElement, U extends HTMLElement>(element: T, children: U[]): Container<T, U[]>;With generic parameter defaults we can reduce it to:
declare function create<T extends HTMLElement = HTMLDivElement, U = T[]>(element?: T, children?: U): Container<T, U>;
A generic parameter default follows the following rules:
- A type parameter is deemed optional if it has a default.
- Required type parameters must not follow optional type parameters.
- Default types for a type parameter must satisfy the constraint for the type parameter, if it exists.
- When specifying type arguments, you are only required to specify type arguments for the required type parameters. Unspecified type parameters will resolve to their default types.
- If a default type is specified and inference cannot chose a candidate, the default type is inferred.
- A class or interface declaration that merges with an existing class or interface declaration may introduce a default for an existing type parameter.
- A class or interface declaration that merges with an existing class or interface declaration may introduce a new type parameter as long as it specifies a default.
Java : What is - public static T foo() {...}?
You've missed the return type out, but apart from that it's a generic method. As with generic types, T
stands in for any reference type (within bounds if given).
For methods, generic parameters are typically inferred by the compiler. In certain situations you might want to specify the generic arguments yourself, using a slightly peculiar syntax:
List<String> strings = Collections.<String>emptyList();
In this case, the compiler could have inferred the type, but it's not always obvious whether the compiler can or can't. Note, the <>
is after the dot. For syntactical reasons the type name or target object must always be specified.
It's possible to have generic constructors, but I've never seen one in the wild and the syntax gets worse.
I believe C++ and C# syntaxes place the generic types after the method/function name.
Can't operator == be applied to generic types in C#?
"...by default == behaves as described above for both predefined and user-defined reference types."
Type T is not necessarily a reference type, so the compiler can't make that assumption.
However, this will compile because it is more explicit:
bool Compare<T>(T x, T y) where T : class
{
return x == y;
}
Follow up to additional question, "But, in case I'm using a reference type, would the the == operator use the predefined reference comparison, or would it use the overloaded version of the operator if a type defined one?"
I would have thought that == on the Generics would use the overloaded version, but the following test demonstrates otherwise. Interesting... I'd love to know why! If someone knows please share.
namespace TestProject
{
class Program
{
static void Main(string[] args)
{
Test a = new Test();
Test b = new Test();
Console.WriteLine("Inline:");
bool x = a == b;
Console.WriteLine("Generic:");
Compare<Test>(a, b);
}
static bool Compare<T>(T x, T y) where T : class
{
return x == y;
}
}
class Test
{
public static bool operator ==(Test a, Test b)
{
Console.WriteLine("Overloaded == called");
return a.Equals(b);
}
public static bool operator !=(Test a, Test b)
{
Console.WriteLine("Overloaded != called");
return a.Equals(b);
}
}
}
Output
Inline:
Overloaded == called
Generic:
Press any key to continue . . .
Follow Up 2
I do want to point out that changing my compare method to
static bool Compare<T>(T x, T y) where T : Test
{
return x == y;
}
causes the overloaded == operator to be called. I guess without specifying the type (as a where), the compiler can't infer that it should use the overloaded operator... though I'd think that it would have enough information to make that decision even without specifying the type.
Related Topics
How to Combine Two Nsdictionary in Swift
Error: Extraneous Argument Label 'No1:' in Call
Generics and Functional Programming in Swift
Swift 5 Coredata Predicate Using Uuid
How to Pass Binding to Child View in the New Navigationstack.Navigationdestination
Swiftui Pass Two Child Views to View
Split String by Components and Keep Components in Place
Tapping an Mkmapview in Swiftui
Why Mark Something Final in Swift Except for Architectural Considerations
Swift Spritekit I Detect a Collison But It Reads the Collision Mulitple Times
How to Scale/Position Nodes Swift Spritekit? Custom View
Uiimagepickercontroller Navigation Bar Tint Color Not Working with iOS 13
Codable/Decodable Should Decode Array with Strings
Swiftui List View Not Updating After Core Data Entity Updated in Another View
Charts Not Plotting in Tableviewcell
New' Is Unavailable: You Cannot Directly Instantiate an Stpissuingcardpin