My question is: is it possible to make one generic method where I can use 2 different types? E.g. an Integer and a String.
There is no practical use for this, but I'd just like to know if it's possible. And if it is, how? :)
You dont need to use generics for this. You can overload the methods. For example
public void method(Integer i){}
public void method(String s){}
If you call method with an integer then it will call the first method. If you call it with a string it will call the second method.
Presumably you mean two different types of parameter?
You could use one method for the String param, and another than takes the integer and passes it on to the String version.
The example types are not good one as the are final. This mean that you can not use them to limit the generic parameter as nothing can inherit from them.
So for that types the answer is No.
But what we can do with Java is:
You can create a method that accept Object type.
public <T> void doStaff(T obj) {
}
You can create a method that is limited to CharSequence as String is final
public <T extends CharSequence> void doStaff(T str){
}
You can create a method that is litmited to more the one interface
public <T extends CharSequence & Comparable<T>> void doStaf(T interf) {
}
But even with so many possibilities we can not create a generic parameter that is valid for Two unrelated types. This would not have sense. As main task of generic type is to provide type safety. And in generally when we use them we should operate with interfaces not classes.
If you want your method to accept Integer and String, try below approach:
public class Test {
public static void main(String[] a) {
method(new String(),new Integer("2"));
}
public static <T extends String, U extends Integer> void method(T t, U u){
}
}
EDIT:
if you want your method to take a single parameter that takes either a String or Integer
try this :
public static <T extends Comparable<T>> void method(T t){
}
Related
Without any introduction to generics, I will post my question straight away. Why is this correct:
static<T extends Object> void m1(List<T> list){
//some code
}
And this is not (doesn't compile):
static void m2 (List<T extends Object> list){
//some code
}
Remember that we could use wildcards in the same approach, which would compile just fine:
static void m2 (List<? extends Object> list){
//some code
}
To sum up, why can we use wildcards declaration in parameters, while using type parameter we must declare it before return type?
There are two main points.
First off, as #akuzminykh said in the comments to the question, the ? wildcard is basically just a way to tell the compiler "I don't know what this is gonna be, just assume it could be anything that derives from this class/interface, kthxbye". It doesn't declare any parameter that you could make use of within the method, no identifier you can call upon, nothing. However, type parameters do exactly that, and if you declare a new one, it's a different story than just "calling" the wildcard which you don't have to declare.
Secondly, think of how you would declare a type parameter for a generic class. Do you think this would be enough?
public class Foo {
public T extends CharSequence getBar() {...}
}
public class Foo {
public <T extends CharSequence> getBar() {...}
}
No, none of these two options would work. In order to use a generic type parameter within a class, you have to declare it along with the type itself, not along with the methods/fields that use them. Like this:
public class Foo<T extends CharSequence> {
public T getBar() {...}
}
And in order to use a generic type parameter within a method, you have to declare it along with the method itself or the type that contains the method, not along with the method parameters that use them.
So i have a bunch of enum's that all extend an interface:
public interface MyInterface {}
I then have several enums that extend the interface:
public enum A implements MyInterface {}
public enum B implements MyInterface {}
I want a function that will accept only enum's that extend this interface. I cannot do:
public void MyFunction(MyInterface input)
because, inside the function, I create an EnumSet using EnumSet.of(input). I cannod do
public <T extends Enum<T>> void myFunction(T input)
because, inside the function, I need to create a Map that needs to be passed to another function. So is there any type-safe way to do this w/o casting?
Edit: Corrected interface definitions.
You can give multiple bounds to your type parameter:
public <T extends Enum<T> & MyInterface> void myFunction(T input)
Note: You're missing return type of the method. I've given void here. Change accordingly. Oh! And please follow Java naming conventions. Method name should start with lowercase letters.
I had an interview test and saw the following code:
EDIT:
public class TestValue {
private Value<SomeValue> defaultValue;
#Test
public void Empty_Value_Has_No_Value() {
Assert.assertFalse(Value.<SomeValue> createEmptyValue()
.hasValue());
}
#Test
public void Default_Value_IsEmpty() {
Assert.assertEquals(Value.<SomeValue> createEmptyValue(),
defaultValue);
}
#Test
public void Non_Empty_Value_Has_Value() {
Assert.assertTrue(new Value<SomeValue>(true, new SomeValue())
.hasValue());
}
}
I had never seen Java generic like
Value.<SomeValue>
The test is to implement Value class with the given unit test code above.
I tried to figure out the Value method signature below (need implementation):
public interface Value<T> {
public boolean hasValue();
public Value<T> createEmptyValue();
}
Any one know, please help?
Thank you
EDIT: Should be like this according to answers below #marlon
public class Value<T> {
public boolean hasValue(){}
public static <M> Value<M> createEmptyValue(){}; //need <M>
}
The key syntax to know:
Value.<SomeValue> //ClassName.<Type>method
is way to invoke static method of a class with parameterized argument.
EDIT: according to #snipes83, syntax to invoke non-static method of a class with parameterized argument.
SomeObject.<Type>method
Value.<SomeValue> it's the way generics are represented for methods.
Using Google Guava's Optional as an example:
Optional<String> email = Optional.<String>of(strEmail);
See Generic Types - Invoking generic methods
Since interfaces cannot declare static methods (shame on you java), just declare your method as static and forget about the interface, like this:
class Value<T> {
public static <T> Value<T> createEmptyValue(){
return null;
}
}
Look at the class Test with the method getEmptyList below:
public class Test {
public <T> List<T> getEmptyList() {
return new ArrayList<T>();
}
}
It returns an empty List containing objects of type T.
If you use Test like this
Test t = new Test();
List<Integer> list = t.getEmptyList();
Then the type inference mechanism is able to infer the type parameter based on the variable type.
However if you need to use the return value of getEmptyList within a method invocation expression like in the following example where the method printList expects a single argument of type List<Integer>, then the type can not be infered from any variable type.
public void printList(List<Integer> list) {
for (int i : list) {
System.out.print(i);
}
}
printList(t.getEmptyList()); // This will FAIL.
In this case you need to specify the type using the following:
printList(t.<Integer>getEmptyList());
1) This is how generic methods are invoked. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/methods.html
2) <SomeValue> in Value.<SomeValue> is optional. Compiler can infer the type. This is called TypeInference. Refer >> http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html
Answer Updated:
3) Value.<SomeValue> createEmptyValue() is right and Value.<SomeValue>createEmptyValue() is right too. Both ways are legal. Just tested it. Didn't notice before.
Although Value is itself obviously typed ( based on the instance variable type of Value<SomeValue>), the static createEmptyValue() method is also typed.
A reasonable assumption, if naming conventions have been adhered to, is that SomeValue extends (or implements) Value.
Although there us no one correct answer, a likely possibility for the signature of Value is:
public class Value<T extend Value> {
public static <V extends Value> V createEmptyValue() {
// some impl
}
}
No static member can use a type parameter, but is it possible to call a static member using the generic type parameter? For example:-
abstract class Agent<A>{
void callAgent();
Agent(){
A.add();
}
}
Here add() is a static method.
There are some C# questions and answers on a similar topic but I'm not too sure how to go about it in Java.
No you cannot do it if A is a generic type. (Bozho answered to fast :) and probably thought A was concrete type.
What will work is the following.
abstract class Agent extends Blah<ConcreteA>{
void callAgent();
Agent() {
ConcreteA.add();
}
}
but it's probably not what you want to do.
After reading your comments it sounds like what you really want to do is:
abstract class Agent<A extends SomeClassThatSupportsAdd> {
void callAgent();
protected abstract A createNew();
Agent() {
A a = createNew();
A.add();
}
}
Your subclasses will have to override createNew().
If you still do not like that you can take a look at AspectJ which will allow you to do some constructor magic (see how spring does #Configurable) but that gets far trickier and complicates things.
Another option is Scala. Java does not do inheritance on static methods so you can't get parameterized modules (groups of functions in some languages this is called a functor ... ocaml). However Scala supports a singleton "object" that does allow for parametric functional polymorphic inheritance.
No, you cannot. The compiler does not know A (which resolves to Object) has the add method.
And you shouldn't need to invoke static methods on generic types in the first place. If you want specific behaviour for each type, define it as non-static, use extends BaseClass in the generics declaration, and invoke it.
Technically, you can also invoke a static method that way, but it's ugly:
class Base {
public static void add() { }
}
class Foo<A extends Base> {
void bar() {
A a = null; // you can't use new A()!
a.add();
}
}
This is not possible because the A type will not necessarily contain an add() method. The compiler will not permit this, because it can't guarantee that it will work.
In fact, you can invoke a static method on a type parameter (although it isn't done dynamically).
Try this:
public class Main<T extends Collections> {
public static void main(String[] args) {
new Main<>().foo();
}
void foo() {
List<Integer> list = Arrays.asList(2, 3, 1);
T.sort(list);
System.out.println(list);
}
}
I have no idea why the language designers decided it was a good idea to allow this.
It is handy to get a value from an enum you don't know beforehand.
public static <T extends Enum<T>> T enumFromName(String name, Class<T> clazz) {
return StringUtils.isEmpty(value) ? null : T.valueOf(clazz, name);
}
Having:
enum ProductType { FOOD, ELECTRONICS, ... }
You can do:
ProductType p = enumFromName("FOOD", ProductType.class);
I guess you can also take advantage of this in your own classes, although I would not recommend using static too much.
You can use reflection for calling static method of class T. For example:
public Agent<T>{
private final Class<T> clazz;
public Agent(Class<T> clazz){
this.clazz = clazz;
executeAddMethodOfGenericClass();
}
public void executeAddMethodOfGenericClass() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method method = clazz.getMethod("add");
method.invoke(null);
}
}
But i can get exception. Be careful.
Given the interface:
public interface BasedOnOther<T, U extends BasedList<T>> {
public T getOther();
public void staticStatisfied(final U list);
}
The BasedOnOther<T, U extends BasedList<T>> looks very ugly in my use-cases. It is because the T type parameter is already defined in the BasedList<T> part, so the "uglyness" comes from that T needs to be typed twice.
Problem: is it possible to let the Java compiler infer the generic T type from BasedList<T> in a generic class/interface definition?
Ultimately, I'd like to use the interface like:
class X implements BasedOnOther<Y> {
public SomeType getOther() { ... }
public void staticStatisfied(final Y list) { ... }
} // Does not compile, due to invalid parameter count.
Where Y extends BasedList<SomeType>.
Instead:
class X implements BasedOnOther<SomeType, Y> {
public SomeType getOther() { ... }
public void staticStatisfied(final Y list) { ... }
}
Where Y extends BasedList<SomeType>.
Update: ColinD suggested
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<T> list);
}
It is impossible to create an implementation such as:
public class X implements BasedOnOther<SomeType> {
public SomeType getOther() { ... }
public void staticStatisfied(MemoryModel list);
} // Does not compile, as it does not implement the interface.
Where MemoryModel extends BasedList<SomeType>, which is needed (as it provides other methods).
It looks as if you don't actually need the type parameter U extends BasedList<T>, if you don't actually need to do anything in the class that requires some specific subclass/implementation of BasedList<T>. The interface could just be:
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<T> list);
}
Edit: Based on your update, I don't think there's any way you can do this. I think you'll have to either just go with your original declaration or make some intermediate type that specifies T, like:
public interface BasedOnSomeType<U extends BasedList<SomeType>>
extends BasedOnOther<SomeType, U>
{
}
public class X implements BasedOnSomeType<MemoryModel> { ... }
That seems like kind of a waste though, and I don't really think the original declaration looks that bad.
What about this?
public interface BasedOnOther<T> {
public T getOther();
public <U extends BasedList<T>> void staticStatisfied(final U list);
}
ColinD is almost correct. What you probably want is this:
public interface BasedOnOther<T> {
public T getOther();
public void staticSatisfied(BasedList<? extends T> list);
}
That's because method arguments are covariant but the generics are invariant. Look at this example:
public test() {
Number n1;
Integer n2; //Integer extends Number. Integer is a more-specific type of Number.
n1 = n2; //no problem
n2 = n1; //Type mismatch because the cast might fail.
List<Number> l1;
List<Integer> l2;
List<? extends Number> l3;
l1 = l3; //No problem.
l1 = l2; //Type mismatch because the cast might fail.
}
Why:
Trying to put an Integer where a Number belongs is covariance and it's usually correct for function arguments.
Trying to put a Number where an Integer belongs is the opposite, contravariance, and it's usually correct for function return values. For example, if you defined a function to return a Number, it could return an Integer. If you defined it to return an Integer, however, you couldn't return a Number because that might be a floating-point, for example.
When you're dealing with generics, the compiler can't tell if the generic parameter (in your case, T) is going to be covariant or contravariant. In your code, for example, T is once a return value and once part of an argument. For that reason, generic parameters are invariant by default.
If you want covariance, use <? extends T>. For contravariance, use <? super T>. As a rule of thumb, you probably always want to specify the covariance/contravariance on all public functions. For private functions it doesn't matter as much because you usually already know the types.
This isn't specific to java, other object-oreiented languages have similar issue.
I recently had a very similar problem.
I would suggest, if you are do not need to specifically refer to MemoryModel, i.e. if U extends BasedList<T> is enough, then I would definitely do what Pepe answered.
However, if you must type check for at least two methods that both methods must use MemoryModel specifically and the type inferencing in Pepe's answer is not enough, then the only way to make the use of the clumsy/verbose parameterized constructor more simplistic, is to exploit the generic method parameter inferencing. You would need to create generic static factory methods for each constructor, where the factory methods do the type inferencing (constructors can't type inference in Java).
How to do this is covered in
Effective Java, by Joshua Block; Item 27: Favor generic methods
I also explained this and quoted the solution (with code) here.