What Does T Equals T Mean in Generics

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
  1. 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 to foo3 contain a Number or a subclass of Number.
    • You can't read an Integer because foo3 could be pointing at a List<Double>.
    • You can't read a Double because foo3 could be pointing at a List<Integer>.
  2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

    • You can't add an Integer because foo3 could be pointing at a List<Double>.
    • You can't add a Double because foo3 could be pointing at a List<Integer>.
    • You can't add a Number because foo3 could be pointing at a List<Integer>.

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
  1. 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 because foo3 could be pointing at a List<Number> or List<Object>.
    • You aren't guaranteed a Number because foo3 could be pointing at a List<Object>.
    • The only guarantee is that you will get an instance of an Object or subclass of Object (but you don't know what subclass).
  2. Writing - Given the above possible assignments, what type of object could you add to List foo3 that would be legal for all the above possible ArrayList assignments:

    • You can add an Integer because an Integer is allowed in any of above lists.
    • You can add an instance of a subclass of Integer because an instance of a subclass of Integer is allowed in any of the above lists.
    • You can't add a Double because foo3 could be pointing at an ArrayList<Integer>.
    • You can't add a Number because foo3 could be pointing at an ArrayList<Integer>.
    • You can't add an Object because foo3 could be pointing at an ArrayList<Integer>.

PECS

Remember PECS: "Producer Extends, Consumer Super".

  • "Producer Extends" - If you need a List to produce T values (you want to read Ts 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 consume T values (you want to write Ts 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



Leave a reply



Submit