I want to know if Vector is holding <String> or <Integer>.
my function public void printVector(Vector <?> v){
I tried if(v instanceof <String>) but the compiler won't allow it.
whats the issue?
A code example that may be relevant:
import java.util.Iterator;
import java.util.Vector;
public class Cool {
public static void main(String[] args) {
Vector<Integer> v;
v = new Vector<>(5);
v.add(Integer.valueOf(5));
test(v);
}
private static void test(Vector<?> v) {
Iterator<?> iterator = v.iterator();
if (iterator.hasNext()) {
System.out.println(iterator.next().getClass());
}
}
}
This will print out class java.lang.Integer.
Your "test" method will have to check the type against a set of superclasses you're interested in (Employee/Customer/etc).
Also, Using vectors is generally considered bad practice in java.
Theoretically, you cannot know, because of type erasure. Basically, it means that you cannot get the generic type of the vector at runtime.
Now, in a real application, if you know that every objects are of the same type, you can get the first one and check its type with instanceof.
Note : this is not a good practice. Avoid that if you can. And as said by the others, you should consider other collections than Vector.
Note : as a rule of thumb, using instanceof is a clue of design flaw. Also, this is a costly operation.
If there is no first element, then your array is empty so you can just drop it.
As has been pointed out, Java's type erasure will make the compile-time generic type information unavailable run-time.
A common workaround for this is to pass the Class of the generic parameter as a method argument. This way you can then check whether the method was indeed passed a list of Customers or Employees:
public void print(List<?> list, Class<?> clazz) {
if (clazz == Employee.class) {
// ...
} else if (clazz == Customer.class) {
// ...
} else {
// ...
}
}
You could then call the method as follows:
Vector<Employee> legacy = new Vector<>();
// do stuff
print(legacy, Employee.class);
Note that resorting to instanceof or class checks is usually a sign of bad object oriented design and in general, you can achieve a more elegant solution through polymorphism, i.e. overriding the print() method for different object types -- or having a single print() method that utilizes different toString() implementations of the domain objects.
Related
I'm fairly new to programming and we do have an exercise, we have to use the Consumer interface, we have a generic class (genClass) that has a Consumer<T> attribute (conAtt). In another class we have to use the accept method of Consumer, but somehow it doesn't work. I have already read through the Java API of the Consumer interface, but it didn't help.
The error message says:
The method accept(capture#4-of ?) in the type Consumer<capture#4-of ?> is not applicable for the arguments (capture#5-of ?)
I know it says not applicable, but why not?
public abstract class GenClass<T> {
protected Consumer<T> conAtt;
public abstract T getData();
}
class Otherclass{
private List<GenClass<?>> helparray= new ArrayList<>();
private void testmethod() {
Iterator<GenClass<?>> hilfe = helparray.iterator();
while (hilfe.hasNext()) {
GenClass<?> help = hilfe.next();
help.conAtt.accept(help.getData());//here is the problem
}
}
}
public class thirdclass extends GenClass<Character> {
#Override
public Character getData() {
return 't';//t is just an example
}
}
This is not really a question about how the Consumer - or other interfaces - in Java work, but about Generics.
Generics aim to simplify the way of writing code and avoid code repetitions. E.g. you need to do a similar task, but for different types you can write it once by using Generics instead of writing it over and over again, just with concrete types being replaced.
For example one day you have the need to keep track of a list of Strings. As easy as that, your going ahead and implementing a solution for that, whereby the first implementation can look like the following (note: a very simplified example, but it'll show the purpose):
public class CustomListString {
private String[] elements = new String[10];
public void add(String newElement) {
int nextFreeIndex = findNextFreeIndex();
elements[nextFreeIndex] = newElement;
}
public String get(int index) {
return elements[index];
}
}
So you can use the above implementation of the List in your code like the following:
public static void main(String[] args) {
CustomListString listOfStrings = new CustomListString();
listOfStrings.add("A");
listOfStrings.add("B");
}
Simple, specific and sufficient!
But the other day, you also have the requirement to keep track of a list of Integers. What to do now?
A way to solve this is to just repeat your previous approach and to implement another CustomList only for the Integers now. Where the corresponding implementation would look like this (the implementation of CustomListString has been copied and all occurrences of String have been replaced by Integer):
public class CustomListInteger {
private Integer[] elements = new Integer[10];
public void add(Integer newElement) {
int nextFreeIndex = findNextFreeIndex();
elements[nextFreeIndex] = newElement;
}
public Integer get(int index) {
return elements[index];
}
}
As you can imagine now already, this is not flexible and can be very cumbersome in the future. This approach will require a new implementation of each type you want to store in the future. So you might end up to also create implementations like CustomListDouble, CustomListCharacter, ... and so on, in which only the type of the elements within the array change - nothing else which would be of importance!
This will additionally lead to the situation, that you'll duplicate a lot of similar code (like findNextFreeIndex() method would have been) and in case of a bugfix need to adjust it in a lot of places instead of in only one.
To solve this issue and remain the type safety in the CustomList.get method Generics have been introduced to Java!
With the Generics approach you'll be able to create a single implementation of the CustomList to store all of your data types without unnecessarily duplicating any shared, basic code and remain the type safety!
public class CustomList<T> {
private Object[] elements = new Object[10]; // Java doesn't supprort easily support generic arrays, so using Object
// here. But the compiler ensures only elements of the generic type T
// will end up here
public void add(T newElement) {
int nextFreeIndex = findNextFreeIndex();
elements[nextFreeIndex] = newElement;
}
#SuppressWarnings("unchecked")
public T get(int index) {
return (T) elements[index];
}
}
Using the new list following the Generics approach we can use it like this now:
public static void main(String[] args) {
CustomList<String> genericList = new CustomList<>();
genericList.add("Hello World");
genericList.add(5); // Compile error! Integer and String types cannot be mixed in
// a single instance of the list anymore => Nice, prevents errors!
genericList.get(0).substring(6); // No compile error, also the compiler knows Strings
// are contained in the list
}
The generic CustomList can now also be reused for any other type and still provide type safety.
What does it mean for your implementation
You can see how we specified the generic type in the CustomList class as T - this is similar like you specified it with ? (probably you'll also want to replace it with T, since you'll run into other issues later when working with the Consumer). But when we used the implementation in our other classes, it wouldn't have been possible to specify it as CustomList<T> or CustomList<?> anymore. We needed to decide and specifiy which exact type of elements the list should contain. This has been the String class, so we specified it as CustomList<String>.
Note: ? is a generic wildcard and means something like "I don't know the real type of the classes now and I'll also don't know it in the future". That's why it'll be hard for you working with the concrete types later in the Consumer. You'll be not able to call any conrete methods on your objects therein. Therefore ? should be avoided as a generic type argument and something like T should be used instead. T means something like "I don't know the real type of the classes now, but I'll do later, as soon as you tell me". Therfore you'll be able to call concrete methods on the objects later in the Consumer, what will simplify your work there a lot.
For your code this means, wherever you want to use your implementation of GenClass<T> you need to specify with which exact kind of elements the class is going to work with. In case of String it is GenClass<String> in case of Character GenClass<Character>.
So the place you'll need to replace the occurrences of GenClass<?> is wherever you refer to it in Otherclass and Otherclass.testmethod.
The way you used the Consumer is fine
I have a HashMap:
HashMap<String, anObjectClass> myHash = new HashMap<String, anObjectClass>();
I have my anObjectClass:
public class anObjectClass {
private String name;
private ArrayList<String> myObjectList = new ArrayList<String>();
}
I have another class that extends my anObjectClass that adds another String:
public class secondObjectClass extends anObjectClass {
String quote;
}
Which means I have two kinds of objects within my HashMap:
My anObjectClass objects which have a String name and an ArrayList of Strings: myObjectList
And my secondObjectClass objects which adds another String: quote.
My question is, if I have a String key, say "ABC". I know I can tell whether or not there is a key "ABC" in my HashMap with the containsKey() method. But once I have found a key "ABC", how do I tell if it is an anObjectClass object or a secondObjectClass object? In other words, how can I tell what kind of object matches with that key? Thank you in advance.
For objects for which you control the definitions, define a boolean
boolean isBaseClass() { return(true); }
and in the subclass define
boolean isBaseClass() { return(false): }
but more generally, use method inheritance instead of this kind of test,
because it can be extended to any family of classes.
// bad
if(x.isBaseClass()) { doThis(); } else { doThat(); }
// better
x.doNextThing()
You can use the keyword instanceof to determine the types of different objects in Java.
In your example, say you are trying to determine the type of an object obj that is either an instance of anObjectClass or secondObjectClass. You can tell the type by using the following code:
if(obj instanceof secondObjectClass) {
// obj is of type secondObjectClass
} else if(obj instanceof anObjectClass) {
// obj is of type anObjectClass
}
This is fine, but beware - types are transitive. That is, an instance of secondObjectClass is also of type anObjectClass because it is a subclass of it. It is therefore helpful to be as specific as possible when using instanceof.
You can also use isAssignableFrom method of Class class.
So your code will look like
if(obj.getClass().isAssignableFrom(BaseClass.class)) {
//bla
}
if(obj.getClass().isAssignableFrom(SuperClass.class)) {
//blabla
}
I like this because I don't have to worry about the order of if else's nor do I need to write nested if elses.
EDIT
By order I meant while using instanceof, your if elses have to be placed in a way that the sub class is checked before the base class instanceof check. Sorry for causing any confusion. Thanks #EJP for pointing out.
Hi guys i got a problem with an unsafe cast operation.
Here is the problem. I gotta Constructor which accepts different types of Orders (PlayList, UserOperations, etc.) or should. So i decided to give it a Parameter as Object and check the type of the received once called. The Problem is one of those is a parameterized ArrayList (ArrayList < PlayList >) and since it is impossible to check a parameterized ArrayList I have to "dig" in. At first step i check if it is an ArrayList, at second I go into it an check the type of its content.
The problem afterwards is I get an unsafe cast warning which i dunno yet how to handle.
Greetings
public Order(int aTyp, Object aOrderContent) {
this.orderTyp = aTyp;
if (aOrderContent instanceof ArrayList< ? >) {
ArrayList<?> objList = (ArrayList< ? >)aOrderContent;
if (objList.get(0) != null && (objList.get(0)) instanceof PlayList) {
playList.addAll((ArrayList<PlayList>)aOrderContent) ;
}
} else if (aOrderContent instanceof UserOP) {
}
}
Rethink your design. Don't make the constructor take an Object. This is too opaque and allows consumers of your code to pass any type. It sounds like you should be using a generic class instead (though it's hard to tell based on your partial example). Possible solution:
// Might need an upper bound on T if you want to limit the allowed parameterizations
class Order<T> {
private final int orderTyp;
private final List<T> someList = new ArrayList<>();
public Order(int aTyp, List<t> aOrderContent) {
this.orderTyp = aTyp;
someList.addAll(aOrderContent);
}
}
Keep in mind it may be better to use an enum instead of int for the orderTyp, if you know (at compile time) all the possible type values.
Side note: if a List is empty, List#get(0) with throw an exception, not return null.
Instead of making the constructor take an Object overload you constructor. Have one take an List<?> and one take a UserOP ect. Also, it would be ideal if all the options for the List extended from the same interface so you could have List<MyInterface> instead of List<?>
How do I write a static method in Java that will take a List, perform an action on each element, and return the result (without affecting the original of course)?
For example, if I want to add 2 to each element what goes in the ... here? The concrete return type must be the same, e.g. if my List is a LinkedList with values 1,2,3 I should get back a LinkedList with values 3,4,5. Similarly for ArrayList, Vector, Stack etc, which are all Lists.
I can see how to do this using multiple if (lst instanceof LinkedList) ... etc... any better way?
import java.util.List;
public class ListAdd {
static List<Integer> add2 (List<Integer> lst) {
...
return result;
}
}
There are already many answers, but I'd like to show you a different way to think of this problem.
The operation you want to perform is known as map in the world of functional programming. It is something we do really all the time in functional languages.
Let M<A> be some kind of container (in your case, M would be List, and A would be Integer; however, the container can be lots of other things). Suppose you have a function that transforms As into Bs, that is, f: A -> B. Let's write this function as of type F<A, B>, to use a notation closer to Java. Note that you can have A = B, as in the example you give (in which A = B = Integer).
Then, the operation map is defined as follows:
M<B> map(M<A>, F<A, B>)
That is, the operation will return a M<B>, presumably by applying F<A, B> to each A in M<A>.
In practice...
There's a brilliant library developed by Google, called Guava, which brings lot's of functional idioms to Java.
In Guava, the map operation is called transform, and it can operate on any Iterable. It has also more specific implementations that work directly on lists, sets, etc.
Using Guava, the code you want to write would look like this:
static List<Integer> add2(List<Integer> ns) {
return Lists.transform(ns, new Function<Integer, Integer>() {
#Override Integer apply(Integer n) { return n + 2; }
}
}
Simple as that.
This code won't touch the original list, it will simply provide a new list that calculates its values as needed (that is, the values of the newly created list won't be calculated unless needed -- it's called a lazy operation).
As a final consideration, it is not possible for you to be absolutely sure that you will be able to return exactly the same implementation of List. And as many others pointed out, unless there's a very specific reason for this, you shouldn't really care. That's why List is an interface, you don't care about the implementation.
Fundamentally, the List interface doesn't make any guarantees that you'll have a way to duplicate it.
You may have some luck with various techniques:
Using clone() on the passed in List, although it may throw, or (since it is protected in Object) simply not be accessible
Use reflection to look for a public no-argument constructor on the passed-in List
Try to serialize and deserialize it in order to perform a "deep clone"
Create some sort of factory and build in knowledge of how to duplicate each different kind of List your code may encounter (What if it's a wrapper created by unmodifiableList(), or some oddball custom implementation backed by a RandomAccessFile?)
If all else fails, either throw, or return an ArrayList or a Vector for lack of better options
You could use reflection to look for a public zero-arg constructor on the result of lst.getClass() and then invoke() it to obtain the List into which you'll place your results. The Java Collections Framework recommends that any derivative of Collection offer a zero-arg constructor. That way, your results we be of the same runtime class as the argument.
Here is a variant which does neither copies nor modifies the original list. Instead, it wraps the original list by another object.
public List<Integer> add2(final List<Integer> lst) {
return new AbstractList<Integer>() {
public int size() {
return lst.size();
}
public Integer get(int index) {
return 2 + lst.get(index);
}
};
}
The returned list is not modifiable, but will change whenever the original list changes.
(This implements the iterator based on index access, thus it will be slow for a linked list. Then better implement it based on AbstractSequentialList.)
Of course, the resulting list will obviously not be of the same class as the original list.
Use this solution only if you really only need a read-only two added view of your original list, not if you want a modified copy with similar properties.
The whole point of using an interface, in this case List, is to abstract the fact that the implementation is hidden behind the interface.
Your intention is clear to me, however: the Clonable interface supports creating a new instance with the same state. This interface might not be defined on your List.
Often it's a good idea to rethink this situation: why do you need to clone the List in this place, this class? Shouldn't your list-creator be responsible for cloning the list? Or shouldn't the caller, who knows the type, make sure he passes in a clone of his list?
Probably, if you look for the semantics as you defined it, you can implement all your supported Lists:
static Vector<Integer> addTwo(Vector<Integer> vector) {
Vector<Integer> copy = null; // TODO: copy the vector
return addTwo_mutable(copy);
}
static ArrayList<Integer> addTwo(ArrayList<Integer> aList) {
ArrayList<Integer> copy = null; // TODO: copy the array list
return addTwo_mutable(copy);
}
static LinkedList<Integer> addTwo(LinkedList<Integer> lList) {
LinkedList<Integer> copy = null; // TODO: copy the linked list
return addTwo_mutable(copy);
}
private <T extends List<Integer>> static T addTwo_mutable(T list) {
return list; // TODO: implement
}
Even, when you don't support a data-type, you'll get a nice compiler error that the specified method does not exists.
(code not tested)
Just to show you that what you want to do is not possible in the general case, consider the following class:
final class MyList extends ArrayList<Integer> {
private MyList() {
super.add(1);
super.add(2);
super.add(3);
}
private static class SingletonHolder {
private static final MyList instance = new MyList();
}
public static MyList getInstance() {
return SingletonHolder.instance;
}
}
It is a singleton (also, a lazy, thread-safe singleton by the way), it's only instance can be obtained from MyList.getInstance(). You cannot use reflection reliably (because the constructor is private; for you to use reflection, you'd have to rely on proprietary, non-standard, non-portable APIs, or on code that could break due to a SecurityManager). So, there's no way for you to return a new instance of this list, with different values.
It's final as well, so that you cannot return a child of it.
Also, it would be possible to override every method of ArrayList that would modify the list, so that it would be really an immutable singleton.
Now, why would you want to return the exact same implementation of List?
OK well someone mentioned reflection. It seems to be an elegant solution:
import java.util.*;
public class ListAdd {
static List<Integer> add2 (List<Integer> lst) throws Exception {
List<Integer> result = lst.getClass().newInstance();
for (Integer i : lst) result.add(i + 2);
return result;
}
}
Concise, but it thows an checked exception, which is not nice.
Also, wouldn't it be nicer if we could use the method on concrete types as well, e.g. if a is an ArrayList with values 1, 2, 3, we could call add2(a) and get an ArrayList back? So in an improved version, we could make the signature generic:
static <T extends List<Integer>> T add2 (T lst) {
T res;
try {
res = (T) lst.getClass().newInstance();
} catch (InstantiationException e) {
throw new IllegalArgumentException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
for (Integer i : lst) res.add(i + 2);
return res;
}
I think throwing a runtime exception is the least worst option if a list without a nullary construcor is passed in. I don't see a way to ensure that it does. (Java 8 type annotations to the rescue maybe?) Returning null would be kind of useless.
The downside of using this signature is that we can't return an ArrayList etc as the default, as we could have done as an alternative to throwing an exception, since the return type is guaranteed to be the same type as that passed in. However, if the user actually wants an ArrayList (or some other default type) back, he can make an ArrayList copy and use the method on that.
If anyone with API design experience reads this, I would be interested to know your thoughts on which is the preferable option: 1) returning a List that needs to be explicity cast back into the original type, but enabling a return of a different concrete type, or 2) ensuring the return type is the same (using generics), but risking exceptions if (for example) a singleton object without a nullary constructor is passed in?
Hi is it possible to cast a List?
i have an abstract class that has a method that takes some sort of List<>, iterate through it in a for loop getting each object in that list and calling the insertItem abstract method that is implemented by the sub class to basically pull out the proper data in the items and then finaly inserting them into a database table.
here is the super class method:
protected void insertAllItemsToDb(List<Object> items, String table) {
// open db and table
database().beginTransaction();
// clear all data from table
clearTable(table);
// call a insert statement to insert each column from an item
for (Object object : items) {
insertItem(object, table);
}
// close db
database().endTransaction();
database().close();
}
In the subclass here is one of the override methods: Which i am able to cast the object fine here.
#Override
protected void insertItem(Object object, String table) {
CalendarEventItem item = (CalendarEventItem) object;
eventItemValue = new ContentValues();
eventItemValue.put(LABEL_EVENTS_TITLE, item.getEventTitle());
eventItemValue.put(LABEL_EVENTS_LOCATION, item.getEventLocation());
eventItemValue.put(LABEL_EVENTS_DATE, item.getEventStartTime()
.getDate());
eventItemValue.put(LABEL_EVENTS_TIME, item.getEventStartTime()
.getTime());
eventItemValue.put(LABEL_EVENTS_TIMEZONE, item.getEventStartTime()
.getTimeZone());
database.insert(TABLE_NAME_EVENTS, null, eventItemValue);
}
i then call that method from the superclass using this:
events = (List<CalendarEventItem>) items;
insertAllItemsToDb(events, TABLE_NAME_EVENTS);
But i recieve a compile error saying you cant cast it. Any ideas on how i can achieve this without having to duplicate the same steps and code you see inside the insertAllItemsToDb()
Use a Type parameter
Add a generic Parameter to the abstract class:
public abstract class BaseClass<T>{
protected abstract void insertItem(T object, String table);
protected void insertAllItemsToDb(List<T> items, String table) {
//...
for (T object : items) {
insertItem(object, table);
}
//...
}
}
Now you don't need any casting, a child class just has to use the correct type:
public class FooBar extends BaseClass<Phleem>{
protected void insertItem(Phleem object, String table){
// ...
}
}
A List<Object> is not a List<CalendarEventItem>, so the compiler is right that they aren't castable. For a quick reason why, here's an example:
final List<Object> listOne = new ArrayList<Object>();
listOne.add("Hello World");
final List<CalendarEventItem> listTwo = new ArrayList<CalendarEventItem>();
listTwo.addAll(listOne); // Correctly disallowed by compiler
// This is what you're trying to do
List<CalendarEventItem> sneakyList = (List<CalendarEventItem>)listOne;
listTwo.addAll(sneakyList);
So casting between two incompatible types is disallowed because it would destroy the type-safety guarantees.
You almost certainly want to be declaring your insertAllItemsToDb method to take a List<?> rather than a List<Object>, since you don't care what the element type is so long as it's a subclass of Object (which is trivially true).
This should prevent you having to cast between inconvertible types, and is generally much nicer to work with.
For more information take a look at the Wildcard Bounds section of Angelika Langer's excellent Java Generics FAQ. In fact, you should probably look over the whole thing if you haven't already. The general principle to take away is that in most cases you should likely use wildcards on collections used for method arguments - the only time you wouldn't is if you both read from and write to the collection (which is actually surprisingly rare).
You could also just declare the method parameter as a regular list and then cast it to whatever generic list you want inside the method, ie your method would be protected void insertAllItemsToDb(List items, String table) and the first line you would cast it: List<CalendarEventItem> newItems = (List<CalendarEventItem>) items... of course implementing whatever type of checking/error catching that you should when doing such a thing.