Java generic static class

Generic Methods

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter’s scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method’s return type. For static generic methods, the type parameter section must appear before the method’s return type.

The Util class includes a generic method, compare, which compares two Pair objects:

public class Util < public static boolean compare(Pair p1, Pair p2) < return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue()); >> public class Pair  < private K key; private V value; public Pair(K key, V value) < this.key = key; this.value = value; >public void setKey(K key) < this.key = key; >public void setValue(V value) < this.value = value; >public K getKey() < return key; >public V getValue() < return value; >>

The complete syntax for invoking this method would be:

Pair p1 = new Pair<>(1, "apple"); Pair p2 = new Pair<>(2, "pear"); boolean same = Util. compare(p1, p2);

The type has been explicitly provided, as shown in bold. Generally, this can be left out and the compiler will infer the type that is needed:

Pair p1 = new Pair<>(1, "apple"); Pair p2 = new Pair<>(2, "pear"); boolean same = Util.compare(p1, p2);

This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets. This topic is further discussed in the following section, Type Inference.

Источник

How to make a Java Generic method static?

The following is a snippet on how to make a java generic class to append a single item to an array. How can I make appendToArray a static method. Adding static to the method signature results in compile errors.

Compile Error: I was actually adding the static modifier incorrect.. Using Collections: Yes using a collection would be ideal yet the question is not about collections vs array’s, my use case requires an array.

Note you’ll need to use (EVIL) reflection to stop client code throwing an exception in some but not all circumstances (nice). It’s best to avoid reference arrays.

6 Answers 6

the only thing you can do is to change your signature to

public static E[] appendToArray(E[] array, E item) 

Important details:

Generic expressions preceding the return value always introduce (declare) a new generic type variable.

Additionally, type variables between types ( ArrayUtils ) and static methods ( appendToArray ) never interfere with each other.

So, what does this mean: In my answer would hide the E from ArrayUtils if the method wouldn’t be static . AND has nothing to do with the E from ArrayUtils .

To reflect this fact better, a more correct answer would be:

public static I[] appendToArray(I[] array, I item) 

Please also be aware that there is absolutely no relationship between the class-level type variable E and the static method type variable E . I consider it much better practice to use a different variable name when declaring generic methods, static or otherwise, inside generic classes.

Читайте также:  Спектральное разложение матрицы python

but in this case I can pass one objects of different types into the params. Like I can pass Integer[] array as first param and Double item.

pinkpanther: True, but it doesn’t do any harm, because the static method only ever operates on an array object that is passed to it via a parameter, so its elements are sure to have the correct type.

public static E[] appendToArray(E[] array, E item) < . 

Static generic methods need their own generic declaration ( public static ) separate from the class's generic declaration ( public class ArrayUtils ).

If the compiler complains about a type ambiguity in invoking a static generic method (again not likely in your case, but, generally speaking, just in case), here's how to explicitly invoke a static generic method using a specific type ( _class_._methodname_ ):

String[] newStrings = ArrayUtils.appendToArray(strings, "another string"); 

This would only happen if the compiler can't determine the generic type because, e.g. the generic type isn't related to the method arguments.

I'll explain it in a simple way.

Generics defined at Class level are completely separate from the generics defined at the (static) method level.

class Greet  < public static void sayHello(T obj) < System.out.println("Hello " + obj); >> 

When you see the above code anywhere, please note that the T defined at the class level has nothing to do with the T defined in the static method. The following code is also completely valid and equivalent to the above code.

class Greet  < public static void sayHello(E obj) < System.out.println("Hello " + obj); >> 

Why the static method needs to have its own generics separate from those of the Class?

This is because, the static method can be called without even instantiating the Class. So if the Class is not yet instantiated, we do not yet know what is T. This is the reason why the static methods needs to have its own generics.

So, whenever you are calling the static method,

Greet.sayHello("Bob"); Greet.sayHello(123); 

JVM interprets it as the following.

Greet.sayHello("Bob"); Greet.sayHello(123); 

Both giving the same outputs.

You need to move type parameter to the method level to indicate that you have a generic method rather than generic class:

public class ArrayUtils < public static E[] appendToArray(E[] array, E item) < E[] result = (E[])new Object[array.length+1]; result[array.length] = item; return result; >> 

This will not work because you have not defined the generic type E. In this case you still have to have generic type in the class definition.

How can I make appendToArray a static method?

To make it static, you need to:

Specifically for your example, that means changing the method signature from this:

public E[] appendToArray(E[] array, E item)  
// same as above, but with "static " before return type E[] public static E[] appendToArray(E[] array, E item)  

The key piece that's easy to miss: the generic type should be added to the signature, appearing just before the return type. Excerpt below from the Java Tutorial on Generic Methods:

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type. For static generic methods, the type parameter section must appear before the method's return type.

Generic methods are methods that introduce their own type parameters. This is similar to declaring a generic type, but the type parameter's scope is limited to the method where it is declared. Static and non-static generic methods are allowed, as well as generic class constructors.

The syntax for a generic method includes a list of type parameters, inside angle brackets, which appears before the method's return type. For static generic methods, the type parameter section must appear before the method's return type.

The Util class includes a generic method, compare, which compares two Pair objects:

public class Util < public static boolean compare(Pair p1, Pair p2) < return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue()); >> public class Pair  < private K key; private V value; public Pair(K key, V value) < this.key = key; this.value = value; >public void setKey(K key) < this.key = key; >public void setValue(V value) < this.value = value; >public K getKey() < return key; >public V getValue() < return value; >> 

The complete syntax for invoking this method would be:

Pair p1 = new Pair<>(1, "apple"); Pair p2 = new Pair<>(2, "pear"); boolean same = Util.compare(p1, p2); 

The type has been explicitly provided, as shown in bold. Generally, this can be left out and the compiler will infer the type that is needed:

Pair p1 = new Pair<>(1, "apple"); Pair p2 = new Pair<>(2, "pear"); boolean same = Util.compare(p1, p2); 

This feature, known as type inference, allows you to invoke a generic method as an ordinary method, without specifying a type between angle brackets.

After understanding this doc , for your question answer is that :

public static I[] appendToArray(I[] array, I item) 

Источник

Java - Generic Static Methods

I have been trying to understand whether it is possible to make a method which infers a generic type based on the return class and calls a static method of that generic type. i.e. Below I create 2 classes both of which implement the getInstances and getAllInstances methods. I then attempt to create use the methods from a generic wrapper. It appears that the super class method is always being run regardless of the return type. For example,

public class ParentClass < public ParentClass()<>public static T getInstance() < return (T) new ParentClass(); >public static List getAllInstances() < ArrayListparents = new ArrayList(); for(int i=0;i <5;i++)< parents.add(new ParentClass()); >return (List) parents; > > 
public class SubclassA extends ParentClass < public SubclassA()<>@SuppressWarnings("unchecked") public static SubclassA getInstance() < return new SubclassA(); >@SuppressWarnings("unchecked") public static List getAllInstances() < ArrayListparents = new ArrayList(); for(int i=0;i <5;i++)< parents.add(new SubclassA()); >return parents; > > 
 public class Wrapper < public Wrapper()< // . some other stuff >public T getInstance() < return T.getInstance(); >public List getAllInstances() < return T.getAllInstances(); >public static void main(String. args) < Wrapper wrapper = new Wrapper(); SubclassA subclassA = wrapper.getInstance(); ParentClass parentClass = wrapper.getInstance(); System.out.println(subclassA.getClass().getName()); System.out.println(parentClass.getClass().getName()); >> 

When running Wrapper I get the following error: Exception in thread "main" java.lang.ClassCastException: ParentClass cannot be cast to SubclassA at Wrapper.main(Wrapper.java:20) Can I do this in Java?

Источник

How to call the static class method for a generic object?

I need to pass the class of a generic type into a class's constructor. The class is SpiceRequest from the RoboSpice Android library for a reference to the constructor. It seems odd that the class requires passing the generic's class into the contstructor, when it could be accessed from the generic type itself, in this case RESULT.class , but maybe I'm wrong about this. Anyway, I'm not looking to change the library's code, but rather need to use a generic type for the generic type of SpiceRequest , Map . Here's my code:

SpiceRequest> request = new SpiceRequest>(. ) < . >; 
public SpiceRequest(final Class clazz)

For . I have tried Map.class with the compiler error: The constructor SpiceRequest>(Class) is undefined. Map.class gives the error: Syntax error on tokens, PrimitiveType expected instead , specifically underlining ? extends Object . It also gives the same error as Map.class . And Map.class gives the same compiler error as well. What is the correct way to get the generic class Class ?

stackoverflow.com/questions/2012306/… has information about this too. It seems there is no elegant way to do this in Java other than explicit up casting and then down casting.

4 Answers 4

There are no class literals for concrete parameterized types or wildcard parameterized types. From Angelika Langer's generics tutorial:

Wildcard parameterized types lose their type arguments when they are translated to byte code in a process called type erasure. As a side effect of type erasure, all instantiations of a generic type share the same runtime representation, namely that of the corresponding raw type. In other words, parameterized types do not have type representation of their own. Consequently, there is no point to forming class literals such as List.class , List.class and List.class , since no such Class objects exist. Only the raw type List has a Class object that represents its runtime type. It is referred to as List.class .

There are no class literals for concrete parameterized types for the same reasons, which in a nutshell are type erasure.

For your purposes, you will just need to do an unchecked cast of the class literal:

Class> c = (Class>)(Class)Map.class; 

Note that the double cast through Class is necessary because a direct conversion from Class to Class> is illegal.

Источник

Оцените статью