I have used below method to check record present in the table.
private static boolean isPresent(StuPersonal object, List<StuPersonal> list)
{
for (StuPersonal candidate : list) {
if (candidate.getFRID().equals(object.getFRID()))
{
return true;
}
}
return false;
}
here StuPersonal is a class and list is a list of class StuPersonal. I need to reuse this method for different classes. How can I do it? I have StuDegree,StuContact,StuCollege,etc and its lists. The process must be done when I pass the classes object and its list. Please advise..
If all of these classes have a getFRID() method, then that should be in an interface (e.g. Identified). Then you can use:
private static <T extends Identified> boolean isPresent(T object, List<T> list) {
String frid = object.getFRID(); // Adjust type appropriately
for (Identified item : list) {
if (item.getFRID().equals(frid)) {
return true;
}
}
return false;
}
Alternatively, as a non-generic method - slightly less safe as it means you can try to find a StuPersonal within a List<StuContact> or whatever:
private static boolean isPresent(Identified object, List<? extends Identified> list) {
String frid = object.getFRID(); // Adjust type appropriately
for (Identified item : list) {
if (item.getFRID().equals(frid)) {
return true;
}
}
return false;
}
Consider using Iterable instead of List, too.
Let each class define equals() method. And then you can just do list.contains(object) which will return boolean. This is the most preferred solution.
<S extends Stu>boolean isPresent(S object, List<S> list) {
for (StuPersonal candidate : list) {
if (candidate.getFRID().equals(object.getFRID())) {
return true;
}
}
return false;
}
where type Stu is a common superclass or interface of types StuDegree,StuContact,StuCollege,etc, which has method getFRID().
Related
I'm trying to resolve this apparently simple generic casting problem :
First, declaring this simple generic object :
public interface GenericObject<T> {}
Second, declaring this working interface :
public interface Generic { // I don't want to do Generic<T>
<T> void setGenericObject(GenericObject<T> obj);
}
Then, let's implements this interface :
public class GenericImpl implements Generic {
private GenericObject<String> genericObject; // This is needed
#Override
public <String> void setGenericObject(GenericObject<String> obj) {
genericObject = obj; // eclipse give me this error :
// Type mismatch: cannot convert from
// interfaces.GenericObject<String> to
// interfaces.GenericObject<java.lang.String>
}
}
How can I solve this error ?
Edit :
Actualy, the only way I have to solve this issue is to do this :
public class GenericImpl implements Generic {
private GenericObject<String> genericObject;
#SuppressWarnings("unchecked") // I don't realy like this
#Override
public <T> void setGenericObject(GenericObject<T> obj) {
genericObject = (GenericObject<String>) obj;
}
}
The real problem is that
public <String> void setGenericObject(GenericObject<String> obj)
where the String has nothing to do with the your intended java.lang.String. Here the String is just a type parameter whose name is String by accident.
Please refer to Is it possible to have an interface method defined with a generic return type and a concrete implementation define the return type?.
Case 1:
If T is not used in Generic, then just use a wildcard.
class Generic {
List<?> list;
void set(List<?> list) {
this.list = list;
}
int size() {
return list.size(); // doesn't care about T
}
}
Case 2:
If T is only used as local variables, then declare <T> on the method
class Generic {
<T> void swapFirstAndSecond(List<T> list) {
T first = list.get(0), second = list.get(1);
list.set(1, first);
list.set(0, second);
}
}
Case 3:
If several fields and methods use the same type T, but the exact type of T is not important, then delacre <T> on the class
class Generic<T> {
List<T> list;
void set(List<T> list) {
this.list = list;
}
T getFirst() {
return list.get(0);
}
}
Case 4:
If T must be a specific type, like String, then don't declare type parameter <T>
class Generic {
List<String> list;
void set(List<String> list) {
this.list = list;
}
boolean isFirstContainsSecond() {
String first = list.get(0), second = list.get(1);
// call String.contains here, so T must be String
return first.contains(second);
}
}
I have an Observer that is expecting two possible objects from an observable: List<Cat> or List<Orange>, mutually exclusive. How might I distinguish which data type was passed to
update(Observable observable, Object data)? I cannot use if(data instanceof List<Cat>) because of type erasure at runtime?
Get the first element in your List (assuming is not empty) and test the type of the element retrieved. You may use instanceof operator to see if the object is in the class hierarchy of the desired class, but if you want a more accurate test, use getClass().equals(YourClass.class).
public void foo(List<Object> list) {
if (!list.isEmpty()) {
Object object = list.get(0);
//using instanceof
if (object instanceof Cat) {
}
if (object instanceof Orange) {
}
//using getClass().equals
if (object.getClass().equals(Cat.class)) {
}
if (object.getClass().equals(Orange.class)) {
}
}
}
i know this is not what really PO want but i think this may helpful. Wrapers can help in this situation. you can create two Class and one interface:
interface SpecialList<T> {
T get(int i);
void add(T item);
}
class CatList implements SpecialList<Cat> {
private List<Cat> list;
...
}
class OrangeList implements SpecialList<Orange> {
private List<Cat> list;
...
}
then Observable can return a SpecialList object. in this case instance of will work.
I want to call a method using a collection of objects that all implement the same interface. Is this possible?
public class GenericsTest {
public void main() {
ArrayList<Strange> thisWorks = new ArrayList<>();
isAllStrange(thisWorks);
ArrayList<Person> thisDoesNot = new ArrayList<>();
isAllStrange(thisDoesNot);
}
public boolean isAllStrange(ArrayList<Strange> strangeCollection) {
for (Strange object : strangeCollection) {
if (object.isStrange())
return true;
}
return false;
}
public interface Strange {
public boolean isStrange();
}
public class Person implements Strange {
public boolean isStrange() {
return true;
}
}
}
You can do this using the <? extends Interface> notation:
public boolean isAllStrange(List<? extends Strange> strangeCollection) {
for (Strange object : strangeCollection) {
if (object.isStrange())
return true;
}
return false;
}
Also, do not use ArrayList directly, instead use List. More of this:
Bounded Type Parameters
What does it mean to "program to an interface"?
Read about WildCard in Genrics.
You can do this using
<? extends Strange >
So I have 3 classes:
Item
GroupItem extends Item
ProductItem extends Item
I am passing a array of Item objects to a class and want to do separate things depending on their class type.
Would using instanceof be an acceptable way of doing this or should I have an internal boolean isGroup() method which will be set on initialisation of the specified sub-class.
class Item {
protected boolean isGroup = false;
public boolean isGroupItem() { return isGroup; }
}
class GroupItem extends Item {
public GroupItem() {
isGroup = true;
}
}
class ProductItem extends Item {
public ProductItem() {
isGroup = false;
}
}
class Promotion {
// Item can be either a group or a list of items
private List<Item> items = new LinkedList<Item>;
public void addItem(Item itemObj) {
items.addItem(itemObj);
}
public List<Item> getItems() {
return items;
}
}
class Checker {
// Items retrieved from Promotion and passed from another class as array
public Checker(Item[] items) {
// either
if(items[0] instanceof GroupItem) {
// Do something ...
}
// or
if(items[0].isGroupItem()) {
// Do something ...
}
}
}
So my questions are:
instanceof or method?
if method, in Item or Promotion?
and, Why? (Just so i can better understand the reasoning)
Thanks in advance
Use different methods on the actual type you want to pass as parameter.
Usually, using instance of means that there is something wrong in your model.
If you need to have different behaviors for different subtypes, it means that you are not really using the parent type. In addition, you are compelled to know the implementation details, which should not be the case.
If the inheritance you have is only a technical one, try to use composition instead of inheritance.
This is the exact place where you should use instanceOf operator .
The instanceof operator compares an object to a specified type. You
can use it to test if an object is an instance of a class, an instance
of a subclass, or an instance of a class that implements a particular
interface.
There is no point to skatch a new method or some boolean property to do this stuff. You can easily identify specific Object of GroupItem by check instanceOf.
you can also use GroupItem.class.isInstance(items[0]) to check the same. like -
if(GroupItem.class.isInstance(items[0])) {
// Do something ...
}
I guess I would try to define why I need to know if it is a group at this point.
Let's say it is to decide if one Item is eligible for a promotion and the promotion rules might change: then I would use instanceof, because you don't want the promotion rules logic to "pollute" your basic objects.
If being a group is an important property of your item and is useful in various contexts (not just the promotion rules), I would include it at the Item level.
The instaceOf operator is a better choice but I would also consider to use the Visitor pattern.
interface Item{
void accept(CheckerVisitor checker);
}
class GroupItem implements Item{
void accept(CheckerVisitor checker){
checker.visit(this);
}
}
class OtherItem implements Item{
void accept(CheckerVisitor checker){
checker.visit(this);
}
}
class CheckerVisitor{
void visit(GroupItem groupItem){
//do specific things to GroupItem
}
void visit(OtherItem otherItem){}
}
class MyClassOfItems{
List<Item> items = ...;
for(Item item : items){
item.accept(new CheckerVisitor());
}
}
So after reading this i chose a different path for my solution. Thanks for everyone who helped.
The solution I chose allows me to not even be bothered with what sub-type the object is (thanks to Assylias and Balázs Mária Németh for making me rethink my structure) as I use abstract classes to just get the information i need.
abstract class Item {
public Item(...) {
initialise();
createSQLSegment();
}
protected String SQLSegment = "";
protected abstract void createSQLSegment();
public String getSQLSegment() {
return SQLSegment;
}
...
}
// Concrete class creates response
class GroupItem extends Item {
...
// Concrete method
protected void createSQLStatement() {
SQLStatement = "...SQL...";
}
}
class ProductItem extends Item {
...
// Concrete method
protected void createSQLSegment() {
SQLSegment = "...SQL..."
}
}
class Promotion {
// Item can be either a group or a list of items? extends Item>;
public void addItem(Item itemObj) {
items.addItem(itemObj);
}
public List<Item> getItems() {
return items;
}
}
class Checker {
// Items retrieved from Promotion and passed from another class as array
public Checker(Item[] items) {
...
for(Item item : Items) {
addPreparedSQLToBatch(item);
}
}
private void addPreparedItemToBatch(Item item) {
...
// No need to know concrete class
SQLString += Item.getSQLSegment();
...
}
}
Thanks again to everyone.
Comments welcome, I'm always learning :-)
Before I look through my generic data structure for a value's index, I'd like to see if it is even an instance of the type this has been parametrized to.
But Eclipse complains when I do this:
#Override
public int indexOf(Object arg0) {
if (!(arg0 instanceof E)) {
return -1;
}
This is the error message:
Cannot perform instanceof check against type parameter E. Use instead its erasure Object since generic type information will be erased at runtime
What is the better way to do it?
The error message says it all. At runtime, the type is gone, there is no way to check for it.
You could catch it by making a factory for your object like this:
public static <T> MyObject<T> createMyObject(Class<T> type) {
return new MyObject<T>(type);
}
And then in the object's constructor store that type, so variable so that your method could look like this:
if (arg0 != null && !(this.type.isAssignableFrom(arg0.getClass())) {
return -1;
}
Two options for runtime type checking with generics:
Option 1 - Corrupt your constructor
Let's assume you are overriding indexOf(...), and you want to check the type just for performance, to save yourself iterating the entire collection.
Make a filthy constructor like this:
public MyCollection<T>(Class<T> t) {
this.t = t;
}
Then you can use isAssignableFrom to check the type.
public int indexOf(Object o) {
if (
o != null &&
!t.isAssignableFrom(o.getClass())
) return -1;
//...
Each time you instantiate your object you would have to repeat yourself:
new MyCollection<Apples>(Apples.class);
You might decide it isn't worth it. In the implementation of ArrayList.indexOf(...), they do not check that the type matches.
Option 2 - Let it fail
If you need to use an abstract method that requires your unknown type, then all you really want is for the compiler to stop crying about instanceof. If you have a method like this:
protected abstract void abstractMethod(T element);
You can use it like this:
public int indexOf(Object o) {
try {
abstractMethod((T) o);
} catch (ClassCastException e) {
//...
You are casting the object to T (your generic type), just to fool the compiler. Your cast does nothing at runtime, but you will still get a ClassCastException when you try to pass the wrong type of object into your abstract method.
NOTE 1: If you are doing additional unchecked casts in your abstract method, your ClassCastExceptions will get caught here. That could be good or bad, so think it through.
NOTE 2: You get a free null check when you use instanceof. Since you can't use it, you may need to check for null with your bare hands.
Old post, but a simple way to do generic instanceOf checking.
public static <T> boolean isInstanceOf(Class<T> clazz, Class<T> targetClass) {
return clazz.isInstance(targetClass);
}
Provided your class extends a class with a generic parameter, you can also get this at runtime via reflection, and then use that for comparison, i.e.
class YourClass extends SomeOtherClass<String>
{
private Class<?> clazz;
public Class<?> getParameterizedClass()
{
if(clazz == null)
{
ParameterizedType pt = (ParameterizedType)this.getClass().getGenericSuperclass();
clazz = (Class<?>)pt.getActualTypeArguments()[0];
}
return clazz;
}
}
In the case above, at runtime you will get String.class from getParameterizedClass(), and it caches so you don't get any reflection overhead upon multiple checks. Note that you can get the other parameterized types by index from the ParameterizedType.getActualTypeArguments() method.
I had the same problem and here is my solution (very humble, #george: this time compiling AND working ...).
My probem was inside an abstract class that implements Observer.
The Observable fires method update(...) with Object class that can be any kind of Object.
I only want to handler Objects of type T
The solution is to pass the class to the constructor in order to be able to compare types at runtime.
public abstract class AbstractOne<T> implements Observer {
private Class<T> tClass;
public AbstractOne(Class<T> clazz) {
tClass = clazz;
}
#Override
public void update(Observable o, Object arg) {
if (tClass.isInstance(arg)) {
// Here I am, arg has the type T
foo((T) arg);
}
}
public abstract foo(T t);
}
For the implementation we just have to pass the Class to the constructor
public class OneImpl extends AbstractOne<Rule> {
public OneImpl() {
super(Rule.class);
}
#Override
public void foo(Rule t){
}
}
Or you could catch a failed attempt to cast into E eg.
public int indexOf(Object arg0){
try{
E test=(E)arg0;
return doStuff(test);
}catch(ClassCastException e){
return -1;
}
}
Technically you shouldn't have to, that's the point of generics, so you can do compile-type checking:
public int indexOf(E arg0) {
...
}
but then the #Override may be a problem if you have a class hierarchy. Otherwise see Yishai's answer.
The runtime type of the object is a relatively arbitrary condition to filter on. I suggest keeping such muckiness away from your collection. This is simply achieved by having your collection delegate to a filter passed in a construction.
public interface FilterObject {
boolean isAllowed(Object obj);
}
public class FilterOptimizedList<E> implements List<E> {
private final FilterObject filter;
...
public FilterOptimizedList(FilterObject filter) {
if (filter == null) {
throw NullPointerException();
}
this.filter = filter;
}
...
public int indexOf(Object obj) {
if (!filter.isAllows(obj)) {
return -1;
}
...
}
...
}
final List<String> longStrs = new FilterOptimizedList<String>(
new FilterObject() { public boolean isAllowed(Object obj) {
if (obj == null) {
return true;
} else if (obj instanceof String) {
String str = (String)str;
return str.length() > = 4;
} else {
return false;
}
}}
);
Let Java determine it and catch the exception bottom line.
public class Behaviour<T> {
public void behave(Object object) {
T typedObject = null;
try { typedObject = (T) object; }
catch (ClassCastException ignored) {}
if (null != typedObject) {
// Do something type-safe with typedObject
}
}
}