Suppose I have an Employee class. How can I implement an ArrayList only containing Employee elements without using generics? That is, without Arraylist<Employee>, how can I restrict the ArrayList to add only Employee objects?
Extend ArrayList and customize add() and addAll() method to check the object being added is instanceof Employee
You could use a wrapper class that holds a private ArrayList field, say called employeeList, has a
public void add(Employee employee) {
employeeList.add(employee);
}
as well as any other necessary methods that would allow outside classes to interact with the ArrayList in a controlled fashion.
I find it much better to use composition for this than inheritance. That way if you wanted to change from an ArrayList to something else, say a LinkedList, or even something completely different, you would have an easier time.
You could use Collections.checkedList() - but why would you want to not use generics?
Subclass the ArrayList class and name it something like EmployeeArrayList.
If you're wanting to avoid generics for their own sake, e.g. for compatibility with very old versions of Java, then extending or wrapping ArrayList won't help - you probably want to find or make another array implementation that has the same functionality.
Basically, ArrayList is just a wrapper for a primitive array that copies and pastes its data into a larger array when necessary, so this isn't especially difficult to write from scratch.
What exactly do you want when you "restrict"? There are two possible places where one could place a restriction: at compile-time or runtime.
Generics is a purely compile-time thing. It helps you write correct code but you can still bypass it and put the wrong type in the array and it won't complain at runtime.
On the other hand, something like Collections.checkedList()is a runtime restrictions. It throws an error at runtime when an object of the wrong type comes. But it does not help you at compile-time if you do not have generics.
So the two things are orthogonal, and neither is a replacement for the other. What exactly do you want?
Related
I'm creating an application where I use genetic algorithm (not implemented yet) to make creatures follow food and avoid obstacles.
I have in my simulation class (where the magic happens) an arraylist where all the creatures are stored. To be noted the arraylist is full of abstract class objects whereas my creatures are all a subclass of Creature.
My question is: how can I make another ArrayList or similar where i can iterate over the arraylist and extract a particular subclass? I had a look and it seems there is no way for me to do so because of how java Collections work. Is there any kind of workaround or some library that could make this possible for me?
It is important for me to have separate lists because I need to apply behaviours to different kind of creature and weigh them according to the "dna" of the creature.
GitHub repository for the whole project: https://github.com/Jamesinvi/Animosity/tree/master/Animosity
I tried this but I get a list of all creatures because they are all of the Creature class
//in PSEUDOCODE i would like to do this:
new ArrayList newlist=new ArrayList<Creature>();
for(Creature old:oldList){
if (old instanceof CreatureSubclass){
newlist.add(old);
}
}
Disclaimer: I am a student so forgive me if this is kind of a stupid question but I am struggling a bit with this. Thanks for the help :)
ArrayList <Creature>oldlist=new ArrayList<Creature>();
ArrayList <Creature>newlist=new ArrayList<Creature>();
for(int i=0;i<oldlist.size();i++){
if (oldlist.get(i) instanceof CreatureSubclass){
newlist.add(oldlist.get(i));
}
}
Totally agree with OldCurmudgeon. You should not extract the subclass.
If you really want to do that, one ugly method is to add a string as a member variable to Creature class called flag. So you could use the string comparison instead of instance of which is very dangerous.
if (oldCreature.flag.equals("SmallCreature"))
{
newList.add(oldCreature); // another possible error: do you need a new copy or just reference?
}
And you could consider use enum class instead of string, which would also be a feasible and simple solution.
public enum CreatureName{SmallCreature, LargeCreature}
And again if you want to apply different behaviors onto the different kinds of the subclass (dna), do you have ever considered the design patterns like strategy or abstract class? The visitor pattern may be a good one mentioned by JB Nizet. But it may be overkill for this question.
When using collections in Java, we are advised to use Interface instead of concrete types.
Like: List<Object> list = new ArrayList<Object>();
But, using ArrayList<Object> list = new ArrayList<Object>(); will also does the same job, right?
Yes, but if you later change your mind and use a LinkedList You have to change much more in your code.
That is the Polymorphism which is the core concept of OOP.
It means ‘a state of having many shapes’ or ‘the capacity to take on different forms’. When applied to OOP , it describes a language’s ability to process objects of various types and classes through a single, uniform interface.
List is a Uniform interface and its Different implementations are like ArrayList ,LinkedList.....etc
Prefer to read :What does it mean to program to a interface?
When you define your list as:
List myList = new ArrayList();
you can only call methods and reference members that belong to List class. If you define it as:
ArrayList myList = new ArrayList();
you'll be able to invoke ArrayList specific methods and use ArrayList specific members in addition to those inherited from List.
Nevertheless, when you call a method of a List class in the first example, which was overridden in ArrayList, then method from ArrayList will be called not the one in the List.
Also the first has the advantage that the implementation of the List can change (to a LinkedList for example), without affecting the rest of the code. This is will be difficult to do with an ArrayList, not only because you will need to change ArrayList to LinkedList everywhere, but also because you may have used ArrayList specific methods.
There's a useful principle: for declared types, use the loosest (vaguest) interface possible (and List is 'looser' than ArrayList).
In practice, this means if you only need to access methods declared in List<Object> on your list instance (which is actually an ArrayList), then declare it as List<Object>. This means you can change your mind on the exact type of list later and you only need to change the line that actually instantiates the ArrayList (or LinkedList or whatever you choose).
This has implications for method signature too: if you were passing around an ArrayList instead of a List, and then changed your mind about it being an ArrayList, you have to go and edit lots of method signatures.
Please read up on Polymorphism if you'd like to know more.
Tangentially related is the Liskov Substitution Principle:
What is the Liskov Substitution Principle?
Interfaces or should I say base calsses are used to generalize things and problems at hand. So when you implement an interface you can always get the specific objects.
For example:
From Animal interface or super class you can always derive specific interfaces or calsses like Lion, but not the other way, becaus its true that a Lion is an animal but several other animals cannot be derived from Lion. Thats why it is advised to make things general and hence use interfaces.
Same applies in your case. You can always get ArrayList and other implementations from a List.
Say you have a class with the following method
public ArrayList<T> foo (ArrayList<T> someInput) {
//Do some operations on someInput here...
return someOutput;
}
Now, what happens if you change the program so that it uses LinkedList objects instead of ArrayList objects? You will get a compiler error wherever this method is called, and you would have to go through and refactor your code so that it accepts LinkedList objects.
If you had programmed to an interface and used a List instead:
public List<T> foo (List<T> someInput) {
//Do some operations on someInput here....
return someOutput;
}
If this was the case, no refactoring would be necessary as both the LinkedList and ArrayList classes implement List so there would be no compiler errors. This makes it incredibly flexible. It does not matter to the method what it takes in and what it returns, as long as the objects implement the List interface. This allows you to define behaviour without exposing any of the underlying implementation.
Its always said its better to use a collection object as below
1) List st = new LinkedList();
2) Map mp = new HashMap();
Than
3) LinkedList st = new LinkedList();
4) HashMap mp = new HashMap();
I agree by defining as above (1,2) I can reassign the same variable (st,mp) to other objects of List, Map interface
But Here I cant use the methods that are defined only in LinkedList, Hashmap which is correct as those are not visible for List, Map . (Please correct me if am worng)
But if am defining a object of HashMap or LinkedList, I want to use it for some special functionality from these.
Then Why is it said the best way to create a collection object is as done in ( 1,2 )
Because most of the time you don't need the special methods. If you need the special methods, then obviously you need to reference the specific type.
Lesson for today: Don't blindly apply programming principles without using your own brain.
But if am defining a object of HashMap or LinkedList, I want to use it for some special functionality from these.
In that case, you should absolutely declare the variable using the concrete class. That's fine.
The point of using the interface instead is to indicate that you only need the functionality exposed by that interface, leaving you open to potentially change implementation later. (Although you'd need to be careful of the performance and even behavioural implications of which concrete implementation you choose.)
I agree by defining as above (1,2) I can reassign the same variable
(st,mp) to other objects of List,Map interface
Yes, it's a general practice called programming against interfaces.
But Here I cant use the methods that are defined only in LinkedList,
Hashmap which is correct as those are not visible for List,Map .
(Please correct me if am worng)
No, you are right.
But if am defining a object of HashMap or LinkedList, I want to use it
for some special functionality from these.
Then Why is it said the best way to create a collection object is as
done in ( 1,2 )
This isn't the best way. If you need to use specific methods of those classes you need the reference to the concrete type. If you need to use those collections from a client class that is not supposed to know the internal implementation than it's better to expose only the interface.
Through interfaces you define service contracts. As you say, should you change the lower implementation of a given interface, you can do it flawlesly without any impact on your current code.
If you need any particular behaviour of the particular classes it's absolutely right to use them. Maps usually extend the AbstractMap class that itself implements Map, making the subclasses inherit those methods.
Of course, many classes throw IllegalOperationException on some defined methods of the Map interface, so that implementation type change is not always flawless (but in most cases, it is, because each map has a particular asset that makes it the most appropiate choice for a given context).
Use the type that suits you, not the one that someone says it's the correct one. Every rule has exceptions.
Because if you use the interface to access the collections, you are free to change the implementation. Eg use a ArrayList instead LinkedList, or a synchronized version of it.
This mostly applies to cases where you have a Collection in a public interface of the class, internally i wouldn't bother, just use what you need.
Studying Java, I've come across generic methods.
public <T> void foo(T variable) { }
That is, a method which takes a parameter with an undecided type (á la PHP?). I'm however unable to see how this would be a good solution - especially since I've come to fall in love with a strongly typed languages after coming from a loose ones.
Is there any reason to use generic methods? If so, when?
Those who are coming from prior to Java 5 background knows that how inconvenient it was to store object in Collection and then cast it back to correct Type before using it. Generics prevents from those. it provides compile time type-safety and ensures that you only insert correct Type in collection and avoids ClassCastException in runtime.
So it provides compile time type-safety and casting. When you want to write complex APIs with complex method signatures it will save you a lot both when writing the API and when using the API and prevents writing lots of code for casting part and catch your errors at compile time. just take a look at java.util.Collection package and see the source code.
As a developer I always want compiler to catch my error at compile time and inform me when I want to compile it then i will fix my errors and at runtime there won't be many errors related to type-safety.
for more info see :
http://javarevisited.blogspot.com/2011/09/generics-java-example-tutorial.html
http://javarevisited.blogspot.com/2012/06/10-interview-questions-on-java-generics.html
Generics, among other things, give you a way to provide a template -- i.e. you want to do the same thing, and the only difference is the type.
For example, look at the List API, you will see the methods
add(E e)
For every list of the same type you declare, the only thing different about the add method is the type of the thing going into the list. This is a prime example of where generics are useful. (Before generics were introduced to Java, you would declare a list, and you could add anything to the list, but you would have to cast the object when you retrieved it)
More specifically, you might want 2 ArrayList instances, one that takes type1 and one that takes type2. The list code for add is going to do the same thing, execute the same code, for each list (since the two lists are both ArrayList instances), right? So the only thing different is what's in the lists.
(As #michael points out, add isn't a true example of a generic method, but there are true generic methods in the API linked, and the concept is the same)
There's nothing non-strongly typed about generic functions in general. The type is resolved and checked at compile time. It's not an undecided type, it's one of a range of possible types (these can be constrained, in your example they are not). At compile time it is known and decided.
As hvgotcodes says, the Collections API contains a number of good examples of this in use.
The main objective of Generic concepts are :
To provide type safety to the Collections so that they can hold only
one particular type of object.
To resolve typecasting problems.
To hold only String type of object a Generic version of ArrayList can be declare as follows :
ArrayList l = new ArrayList ();
To know more : http://algovalley.com/java/generics.php
I'm trying to declare an enum type based on data that I'm retrieving from a database. I have a method that returns a string array of all the rows in the table that I want to make into an enumerated type. Is there any way to construct an enum with an array?
This is what I tried, but from the way it looked in eclipse, it seemed like this just created a method by that name:
public enum ConditionCodes{
Condition.getDescriptions();
}
Thank you in advance!
You can't.
The values of an enum must be known at compile time. If you have anything else, then it's not an enum.
You could come rather close via an implementation that's similar to the old typesafe enums that were used before the Java language introduced support for this technique via the enum keyword. You could use those techniques but simply replace the static final fields with values read from the DB.
For your enum to be useful it has to be nailed down at compile time. Generating the enum from the database query would imply you expect to see new enum values at runtime. Even if you created a code generator to create your enum class on the fly using the database query, you wouldn't be able to reference those enum values in your code, which is the point of having them.
It's difficult to see how any compiler could support this.
The whole point of an enum is supposed to be that you get compile-time checking of the validity of your values. If, say, you declare an enum "enum MyStatusCode {FOO, BAR, PLUGH}", then in your code if you write "MyStatusCode.FOO" everything is good, but if you write "MyStatusCode.ZORK" you get a compile-time error. This protects you from mis-spelling values or getting confused about the values for one enum versus another. (I just had a problem recently where a programmer accidentally assigned a delivery method to a transaction type, thus magically changing a sale into an inventory adjustment when he meant to change a home delivery into a customer pick-up.)
But if your values are defined dynamically at run-time, how could the compiler do this? If you wrote MyStatusCode.ZORK in the above example, there is no way the compiler could know if this value will or will not be in the database at runtime. Even if you imagined a compiler smart enough to figure out how the enum was being populated and checking the database to see if that value is present in the appropriate table NOW, it would have no way of knowing if it will be there when you actually run.
In short, what you want is something very different from an enum.
If you want to get really crazy, I think annotation processing can do this. Annotation processing lets you hook the compiler and have it magically modify things when your #annotation is present.
Naturally, the values in the enum will be whatever values were available at compile time.
No, that's not possible because the enum type must be defined at compile time and what you're looking for is to dynamically create it.
Perhaps you'll be better if use a class instead.
I think here you are going to need a List or Set along with some utility methods for searching and comparison.
So here's your List
List<String> conditionCodes = new ArrayList<String>();
//Somehow get Rows or POJO Beans from database with your favorite framework
Collection<Row> dbRows = getConditionCodes();
for(Row curRow : dbRows)
conditionCodes.add(curRow.getName());
And to search
public boolean conditionExists(String name) {
return conditonCodes.contains(name);
}
public String getCondition(String name) {
return conditionCodes.get(name);
}
(of course you would probably want to use List's own methods instead of making your own)
More than you can't, you don't want to. Every enum, even Java's fairly cool enums, is code oriented.
It's exactly the same as a collection, but with an enum you tend to write duplicate code whenever you encounter it--with a collection you are more likely to write a loop.
I suggest you create a class with a private constructor and have it create the instances of itself, then provide a getInstance(String) to retrieve an instance. This is like the old typesafe enum pattern.
In the long run, however, it's better if you can manage to get enough intelligence into that class where you aren't ever differentiating on a specific instance--going from the "Enum" way of doing it:
if(myEnum.stringValue.equals("EnumTarget"))
executeCode();
To the OO way of doing it:
myEnumLikeObject.executeCode();
Moving the code you wish into the "enum"--preferably delegating directly to a contained object that is instantiated and set into the "enum" at creation time.