Can a Condition Be Used to Determine the Type of a Generic

How to check if a generic type implements a specific type of generic interface in java?

Java implements erasure, so there's no way to tell on runtime if genericObject is an instance of Set<String> or not. The only way to guarantee this is to use bounds on your generics, or check all elements in the set.

Compile-time Generic Bounds

Using bounds checking, which will be checked at compile-time:

public <T extends SomeInterface> void genericMethod(Set<? extends T> tSet) {
// Do something with tSet here
}

Java 8

We can use streams in Java 8 to do this natively in a single line:

public <T> void genericMethod(T t) {
if (t instanceof Set<?>) {
Set<?> set = (Set<?>) t;
if (set.stream().allMatch(String.class:isInstance)) {
Set<String> strs = (Set<String>) set;
// Do something with strs here
}
}
}

Java 7 and older

With Java 7 and older, we need to use iteration and type checking:

public <T> void genericMethod(T t) {
Set<String> strs = new HashSet<String>();
Set<?> tAsSet;
if (t instanceof Set<?>) {
tAsSet = (Set<?>) t;
for (Object obj : tAsSet) {
if (obj instanceof String) {
strs.add((String) obj);
}
}
// Do something with strs here
} else {
// Throw an exception or log a warning or something.
}
}

Guava

As per Mark Peters' comment below, Guava also has methods that do this for you if you can add it to your project:

public <T> void genericMethod(T t) {
if (t instanceof Set<?>) {
Set<?> set = (Set<?>) t;
if (Iterables.all(set, Predicates.instanceOf(String.class))) {
Set<String> strs = (Set<String>) set;
// Do something with strs here
}
}
}

The statement, Iterables.all(set, Predicates.instanceOf(String.class)) is essentially the same thing as set instanceof Set<String>.

Assigning datatype to a generic type of variable based on a condition in Java

I changed the class names.

class SOQ<T>
{

T defaultValue;
String value;

}

class SOQ_Impl
{

private void test(String datatype)
{

switch (datatype)
{

case "Integer": {
SOQ<Integer> test = new SOQ<>();
test.defaultValue = 3;
actionsCommonForAllPossibleDataTypes(test);
break;
}

case "String": {
SOQ<String> test = new SOQ<>();
test.defaultValue = "dummy";
actionsCommonForAllPossibleDataTypes(test);
break;
}

}

}

private void actionsCommonForAllPossibleDataTypes(SOQ<?> test)
{

// some other actions common for all possible data types

}

}

You declared the type with a <?> parameter, and that is what is causing you problems. I resolved this by not declaring the variable I was going to use until after I knew what type I wanted it to be.

Under what conditions is unit a type?

I believe the rule is that a method that is statically known to have return type unit will be compiled to a .NET method with return type void in the .NET type system (by statically known, I mean in contrast to a generic method or a method on a generic type which uses a type parameter as the return type). At invocations, the compiler hides the distinction between methods that return void and methods that return true unit values at the CLR level.

The problem in your example occurs because properly implementing the generic interface actually requires a unit return type at the CLR level (and the CLR does care about the distinction between unit and void). In other words, the problem occurs if and only if you want to override a method which returns a type parameter of a generic class by a method which is statically known to return unit (based on substituting unit for that type parameter). By override here, I mean either implementing abstract methods on classes or interfaces or overriding non-sealed methods on classes.

As Tamil points out, one way to work around this limitation is to ensure that you use F# functions instead of methods. Another workaround is to introduce an extra concrete class into the hierarchy which has a dummy generic type parameter (say the extra class is T<'unit>), and to return Unchecked.defaultof<'unit> instead of () wherever that would cause problems. Then you can derive an additional non-generic concrete class T from T<unit> and everything will work fine.

Testing if object is of generic type in C#

If you want to check if it's an instance of a generic type:

return list.GetType().IsGenericType;

If you want to check if it's a generic List<T>:

return list.GetType().GetGenericTypeDefinition() == typeof(List<>);

As Jon points out, this checks the exact type equivalence. Returning false doesn't necessarily mean list is List<T> returns false (i.e. the object cannot be assigned to a List<T> variable).

C# Generics and Type Checking

You could use overloads:

public static string BuildClause(List<string> l){...}

public static string BuildClause(List<int> l){...}

public static string BuildClause<T>(List<T> l){...}

Or you could inspect the type of the generic parameter:

Type listType = typeof(T);
if(listType == typeof(int)){...}

Generic class: conditional method based on type

Nope but you can probably accomplish something similar with interfaces

interface IMyType
{
//...what ever method/properties are shared for all
}

public class MyType<T> : IMyType
{
public T getValue() { return value; }
//...shared methods
}

public class MyTypeOtherSide : IMyType
{
//...shared methods
}

you'd then need to declare the variables as IMyType and only use MyType<T> when you know that it is of that type



Related Topics



Leave a reply



Submit