Java - Interfaces and methods - java

I'm looking through some interfaces at the moment and I'm wondering why this does not work:
interface I {
public void doSomething(String x);
}
class MyType implements I {
public int doSomething(String x) {
System.out.println(x);
return(0);
}
}
Basically, why can't I implement the method in the interface? THey have different signatures as one has a return type? Isn't the name, parameters and return type what make a method unique?

You can't have different return types. Imagine the following
class Foo implements I {
public int doSomething(String x) {
System.out.println(x);
return(0);
}
}
class Bar implements I {
public void doSomething(String x) {
System.out.println(x);
return;
}
}
List<I> l = new ArrayList();
l.add(new Foo());
l.add(new Bar());
for (I i : l) {
int x = i.doSomething(); // this makes no sense for Bar!
}
Therefore, the return types must also be the same!

Yeah, you're basically correct. Java doesn't allow overloading methods by return type, which would be neat. However, the interface return type must still match.

The method signature consists of the method's name and the parameters types, so you can't declare more than one method with the same name and the same number and type of arguments, because the compiler cannot tell them apart.

Think of a typical use for interfaces: e.g. anything implementing the java List interface must implement boolean add(Object o)
The caller is probably going to do something like:
if (!impl.add(o)) { /* report error */ }
If you were allowed to change the return type, you'd hit all types of problems.
void add(Object o)
if (!impl.add(o)) { // ... your method returns void, so this makes no sense
float add(Object o)
if (!impl.add(o)) { // float to boolean ? are you sure that is what you meant?

Related

Interfaces as parameters (Restrictions)

I came across an AP CSA question which had me puzzled for a while. It was basically an incomplete method that looked like this:
public static void methodMan(Comparable c) {.....}
The question first asked if it was valid to use the comparable interface in the parameter listing, then it asked if there were any restrictions on the comparable object. I was stuck between the choices that said either the object c that is being passed needs to be casted or initialized as a comparable or the object c could be any object that implements the comparable interface. Which one is it, and if it isn't either, what would be a restriction on the object c?
Yes it is valid to use interfaces as a parameter in methods and yes object c can be any object that implements the interface. The only caveat to the second portion is if there is a special method that needs to be invoked that the interface does not implement then you will need to cast it to the class first to get the method For Example:
public class MyComparable implements Comparable<String> {
private String item;
public MyComparable(String item) {
this.item = item;
}
#Override
public int compareTo(String o) {
return this.item.compareTo(o);
}
public Integer doThis() {
return 100;
}
public Integer compareSample(Comparable<String> c) {
if (c instanceof MyComparable) {
return ((MyComparable)c).doThis();
}
return c.compareTo(this.item);
}
}
compiles like a charm:
public static void methodMan (Comparable c) {
out.println ("we ignore c");
}
public static void main (String args[])
{
Comparable c1 = new String ();
methodMan (c1);
methodMan ((Comparable) c1);
String s2 = new String ();
methodMan (s2);
methodMan ((Comparable) s2);
}
and runs like a charm.

Casting INSIDE the Generic classes in java

I know that we can skip casting by adding using the Generics in java as follows. (When we are using it outside of the Generic class.)
But if we are doing some logics on the type object (T item) inside the generic class (Container<T>) we should check the instance of and specially cast isn't it? So we can use it to skip casting out side the generic classes.
Please check the commented code in the public void setItem(T item) method.
I want to know whether my understanding is correct or am I missing something
Client.java
public class Client {
public static void main(String[] args) {
// String container
Container<String> stringContainer = new Container<String>();
stringContainer.setItem("Test");
//stringContainer.setItem(new StringBuffer("")); // compilation error, type safety checking
System.out.println(stringContainer.getItem().toUpperCase()); // No need to cast
// Integer container
Container<Integer> integerContainer = new Container<Integer>();
integerContainer.setItem(123);
//integerContainer.setItem("123"); // compilation error, type safety checking
System.out.println(integerContainer.getItem().intValue()); // No need to cast
}
}
Container class
class Container<T> {
private T item;
public T getItem(){
return item;
}
public void setItem(T item){
/* If I' doing some thing on item then I have to check the instance of and cast isn't it?
if(item instanceof String){
System.out.println("setItem().((String)item).toUpperCase() : " + ((String) item).toUpperCase());
}
*/
this.item = item;
}
}
Reference : http://nandirx.wordpress.com/category/java-2/generics-java/
As others have said, you shouldn't ever downcast a generic type as it defeats the purpose of generics.
You should use bound generics instead. A bound generics allows you to require a generic be of a specific type. This allows you to access values in the specific type without needing to cast.
This doesn't make sense with the String class as String is marked final and so cannot be extended, but for the future, try something like this.
public interface Shape{
double getArea();
}
public class Rectangle implements Shape{
double width;
double height;
public double getArea(){ return width*height;}
}
//this collection can hold Shape, or any type implementing shape.
public class MyShapeCollection<T extends Shape>{
List<T> shapes;
public double getAreaSum(){
double areaSum = 0;
for(Shape s : shapes){
areaSum += s.getArea();
}
return areaSum;
}
}
public static void main(String[] args){
MyShapeCollection<Rectangle> rectangles = new MyShapeCollection<Rectangle>();
//bad code monkey. String does not implement Shape!
//this line won't compile. including it for demonstration purposes.
MyShapeCollection<String> willNotCompile = new MyShapeCollection<String>();
}
If your collection will only hold strings, you don't need generics.
Yes, your understanding is correct.
Adding type specific code here, however, defeats the purpose of generics.
A better solution would be the following.
Client.java
public class Client {
public static void main(String[] args) {
// String container
Container<String> stringContainer = new StringContainer();
stringContainer.setItem("Test");
//stringContainer.setItem(new StringBuffer("")); // compilation error, type safety checking
System.out.println(stringContainer.getItem().toUpperCase()); // No need to cast
}
}
Container.java
class Container<T> {
private T item;
public T getItem(){
return item;
}
public void setItem(T item){
this.item = item;
}
}
StringContainer.java
class StringContainer extends Container<String> {
#Override
public void setItem(String item){
System.out.println( item.toUpperCase() );
super.setItem( item );
}
}
Right, or you could overload the setItem() method for different types of parameters, but that's actually even worse.
Yes, for your case casting is necessary. Because you are using string functions specifically.
But its like you are not using generic feature.
If you wanna to print item, then you can override toString() method of each item, and you can directly put item object in sysout(). By doing so, there will be no casting needed and all code get generic for all items.
What you say here.

Overloading / generics in Java

I want to run certain tests in Lists. The Lists can contain entirely different classes.
I have one method to check the consistency of the list - not null, not empty, no more than x elements. This is common to all the lists. Then I want to test each of the objects, using overloading.
The idea would be something like:
public static <T> void check(List<T> list) {
//do general checks
for (T element : list) {
check(element);
}
}
and then
public static void check(SomeType element) {...}
public static void check(SomeOtherType element) {...}
But I also had to add a method like this:
public static void check(T element) {...}
And this was called at runtime - not my other methods with the specific classes. Although the class was exactly the same. I'm evidently missing some generics understanding.
Now if I don't use the general method at all and try to solve it this way:
public static void check(List<SomeType> list) {...}
public static void check(List<SomeOtherType> list) {...}
Compiler error - "Method check(List) has the same erasure check(List) as another method..."
So is there any elegant solution for this? I could just use different method names but would like to know how it's possible without that.
Thanks!
This isn't something about generics that you're missing. Java does not have double dispatch. The call to check must be resolved at compile-time, and check(T) is the only match since the compiler can't tell if T is SomeType or SomeOtherType in a given scenario. It needs to choose one method to call that will work for all possible Ts.
This is sometimes solved using the visitor pattern.
The problem should be solved by the caller. When it instanciate your class with a concrete type for T, it should also pass an instance of Checker<T> with the same concrete type:
public class SomeClass<T> {
private List<T> list;
private Checker<T> checker;
public SomeClass(Checker<T> checker) {
this.checker = checker;
}
public void check() {
checker.check(list);
}
}
public interface Checker<T> {
public void check(List<T> list);
}
...
SomeClass<Foo> someClass = new SomeClass<Foo>(new Checker<Foo>() {
#Override
public void check(List<Foo> list) {
// do whatever you want here
}
});
You can use instanceof to dispatch:
public static <T> void check(List<T> list) {
for (T element : list) {
check(element);
}
}
public static void check(T t) {
if (t instanceof SomeType) {
SomeType someType = (SomeType) t;
// code for SomeType ...
} else if (t instanceof OtherType) {
OtherType otherType = (OtherType) t;
// code for OtherType ...
} else {
// we got a type that we don't have a method for
}
}
With generics, the type parameter is actually erased during compilation, and the list object don't know anything about the static type of the object it contains. Since it doesn't know it, it can not use overloading to call methods with different parameters, because Java doesn't support multiple dispatch.
You have then three choices:
Make your objects implement a Checked interface with a check method that does the check logic. Downside is that the check logic is now dispersed in several places and it is not practical if you have objects of classes you don't have control of.
Use instanceof to call explicitly the check methods according to the dynamic type of the object. Downside is you potentially end up with a big if/else block a bit harder to maintain.
Implement the visitor pattern. Downside is that you have to change the object classes too, but the check logic stay in a single place.
Since the type of the variable is lost in check(List<T> list) you have two options:
1. Do different things by checking runtime type
check(T element) {
if (element.getClass().equals(SomeType.class)) {
check((SomeType) element);
} elseif (element.getClass().equals(SomeOtherType.class)) {
check((SomeOtherType) element);
}
This can be made a little more sophisticated, for example by wrapping each check in a Callable and using a Map<Class, Callable>
This is similar to visitor pattern.
2. Calling a virtual method on the element to be checked itself
If the checking logic can be pushed to the object to be checked itself (this is not necessarily a bad thing) then you don't need to check types:
interface Checkable { void check(); }
class SomeType implements Checkable { .... }
class SomeOtherType implements Checkable { .... }
Then:
public static <T extends Checkable> void check(List<T> list) {
for (T element : list) {
element.check();
}
}
These are the only two options, any implementation has to be a variation on one of these

How do I define the return type inside a Java generics method?

I have a generic method, for example:
public static<T> T execute(...) {
...
}
How can I define what type T is in the method body? For example:
if (T == String) {
// do something with strings
// return string;
}
if (T == Bitmap) {
// do something with bitmap
// return bitmap;
}
I tried the following, but it didn't work:
T par = null;
if(par instanceof String) {
// do something with strings
// return string;
}
I tried declaring par like below, but that didn't work either.
T par = (T) null;
T par = (T) new Object();
You could probably do something like this:
public static <T> T execute(Class<T> t) {
if(String.class == t) {
}
}
If your code only supports a discrete set of data types, you don't want to use generics. As mentioned in the comments on the original post, this situation calls for overloaded method calls.
Consider, for example, a situation where you support Strings, Integers, and Doubles, but you don't have specific logic for other data types. You would define your methods such as:
public static String execute(String s) { ... }
public static Integer execute(Integer i) { ... }
public static Double execute(Double d) { ... }
public static Object execute(Object o) { ... }
The first three methods would define the logic for the three discrete data types you do support, while the final would define logic and/or error handling for any other data types you do not support. (Of course, this doesn't cover primitives not of int or double type, but this is just an example.)
Generics were initially added to Java to support a Collection knowing exactly what it contained. It was a way of guaranteeing that a List held only Strings by declaring it a List<String>, for example. This capability was then extended, but the basic concept held -- guarantee that if you put an unknown object of type X in, even if you don't know what X is at compile time, you can write logic for getting that same type X out. (This article is an interesting read, if out-dated.)
This does not mean it should be used where the logic applied in a method or class is dependent on the data type of the input. It should be used where it doesn't matter the incoming data type, and the same logic will be applied consistently across the unknown data type X. So if you have different logic for String than Doubles, you should not be using generics.
tl;dr:
Since the original post indicated different logic based on the data type of the input parameter, therefore, generics are not appropriate to be used. Overloading the execute method based on the supported data types should be used instead.
T Here is known as Type Parameters.
// here will define the type of T in the method go()
public interface Comparable<T> {
public int compareTo(T t) {
// do something...
}
}
For eg:
I am having a class Song, and i want to sort the songs on the basis of its title.
public class Song implements Comparable<Song> {
private String title;
public void compareTo(Song s) {
title.compareTo(s.title());
}
public void setTitle(String s) {
this.title = s;
}
public void getTitle() {
return this.title;
}
public String toString() {
return getTitle();
}
}
If you're splitting the functionality in code that way already, and the inputs are the same, you'd probably be well served with different functions. So instead of(using Jeshurun's answer)
public static <T> T execute(Class<T> t)
{
if(String.class == t) {
}
}
BitMap b = execute(BitMap.class);
You would have
public BitMap bitmapExecute(...)
{
commonWork();
//do bitmap stuff
}
public String stringExecute(...)
{
commonWork();
//do String stuff
}
BitMap b = bitmapExecute(...);
String s = stringExecute(...);
If there's a large block of common code, with only a small section different based on type, you can move that common code to its own function.
public someObject commonWork(...)
{
//Do common stuff
}
As long as you are making the decision about the type at compile time, you shouldn't have to have instanceof blocks.

Java generics (template) specialization possible (overriding template types with specific types)

I'm wondering what are the options to specialize generic types in Java, i.e. in a templated class to have specific overrides for certain types.
In my case I was a generic class (of type T) to return null usually, but return "" (the empty string), when T is the String type, or 0 (zero) when its the Integer type, etc.
Merely providing a type-specific overload of a method produces a "method is ambiguous" error:
e.g.:
public class Hacking {
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
Bar<String> barString = new Bar<String>();
// OK, returns null
System.out.println(barInt.get(new Integer(4)));
// ERROR: The method get(String) is ambiguous for the type Bar<String>
System.out.println(barString.get(new String("foo")));
}
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
}
Is the only option to subclass the generic class with a specific type (see StringBar in the following example?
public static void main(String[] args) {
Bar<Integer> barInt = new Bar<Integer>();
StringBar barString2 = new StringBar();
// OK, returns null
System.out.println(barInt.get());
// OK, returns ""
System.out.println(barString2.get());
}
public static class Bar<T> {
public T get() {
return null;
}
}
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
}
Is this is the only way, it's a bit of a pain to have to create a subclass for every type I want to specialize instead of an overload of get() in the Bar class.
I'm guessing I could check the instanceof in the Bar.get() method, e.g.
T get(T t) {
if (t instanceof String) return "";
if (t instanceof Integer) return 0;
else return null;
}
However I've been taught to avoid instanceof and use polymorphism when possible.
All things considered, the concensus appears to be that the StringBar method mentioned in the question is the only way to go.
public static class StringBar extends Bar<String> {
public String get() {
return "";
}
}
Generics in Java are very different from templates in C++ in this respect. It is not possible to write a specific version of a generic class to do something different for a particular case, as C++ can do. It is also not possible to determine at run time what T is - this is because that information is not passed into the byte code (object code) and so doesn't even exist at runtime. This due to something called "type erasure".
BarString and BarInt would be the obvious way of doing this, but there are improvements you can make. For example you can write a generic Bar to cover the common cases, and then write specialized BarString and BarInt to implement special cases. Ensure that the instances can only be created through a factory, which takes the class of the object to be processed:
class Bar<T> {
class BarString extends Bar<String> {
// specialist code goes here
}
static Bar<T> createBar(Class<T> clazz) {
if (clazz==String.class) {
return new BarString();
} else {
return new Bar<T>;
}
That probably won't compile, but I don't have the time to work out the exact syntax. It does illustrate the principle.
The compiler is actually correct, because the following code is compile-time checked (Bar<String> barString = new Bar<String>();) when compiled, from
public static class Bar<T> {
public T get(T x) {
return null;
}
public String get(String x) {
return "";
}
}
to
public static class Bar<String> {
public String get(String x) {
return null;
}
public String get(String x) {
return "";
}
}
and is ambiguous as you can't have 2 identical methods with the same return types and the same parameter arguments.
See an explanation by Jon Skeet's:
What is the concept of erasure of generics in java?
Java Generics - Types erasures - when and what happens?
You can subclass Bar<T> and create StringBar (note I removed the static keyword) and override get() method.
public class BarString extends Bar<String> {
#Override
public String get(String x) {
return "";
}
}
Generics in Java aren't made for specialization. They're made for generalization! If you want to specialize for certain types, you should be specializing...through a subclass.
Often you don't need to do something in a specialized manner however. Your StringBar example is kind of contrived because you could have this:
public class Bar<T> {
private final T value;
public T get() {
return value;
}
}
I don't see why you need to specialize for a String here.

Categories