Java ArrayList - can't read back properties of objects - java

I want to be able to make an array list of objects, and then be able to edit and read back some simple properties of each object. In this case, a String (colour) and integer (X). I can't seem to make the simple code below work. Note that I am aware people sometimes use the <> notation with array lists, but I have read that it should be possible without, and at the moment I am very new to Java and wish to keep things as simple as possible.
At the moment I get an error on the line which is commented out (cannot find symbol X)
import java.util.ArrayList;
public class ArrayList_of_Objects {
public static void main(String[] args)
{
ArrayList al = new ArrayList();
for(int i =0;i<5;i++)
{
MyObj ob1 = new MyObj();
ob1.X = i + 5;
al.add(ob1);
//System.out.println("X: "+al.get(i).X);
}
for(int j=0;j<5;j++)
{System.out.println("X: "+al.get(j).X);}
al.get(3).X=4;
al.get(3).colour="orange";
System.out.println(al.get(3).X);
System.out.println(al.get(3).colour);
}
}
class MyObj
{
int X;
String colour;
}

Yes, you need to use generics to say what kind of object will be in your list:
ArrayList<MyObj> al = new ArrayList<MyObj>();
Otherwise the compiler doesn't know that al.get(3) is meant to return a MyObj rather than just anything. With this code, it will not only fix the get calls - it will stop you from accidentally adding objects of inappropriate types to the list.
Also, it's usually preferred to declare variables as an appropriate interface type, such as:
List<MyObj> al = new ArrayList<MyObj>();
(There are times where you really need it to be the concrete type, but generally prefer programming to interfaces.)
Generics is a massive topic, but the tutorial linked at the start of this answer should get you going. The Java Generics FAQ is a great resource for finding out more.

Change
ArrayList al = new ArrayList();
to
ArrayList<MyObj> al = new ArrayList<MyObj>();
What you have right now is an array list of Object rather than an array list of MyObj, and Object has no knowledge of MyObj.X.

Use ArrayList<MyObj> al = new ArrayList<MyObj>(); instead

Related

Introducing a String to define a type

I want to know if there is a way to do this:
String **type** = "Player"
ArrayList<**type**> players = new ArrayList();
What I mean is defining an object type with a variable String. I put "player" and it can just be Player here, but what about a method that you can introduce a variable type to? Something like this:
public static void main (String[] args)
{
system.out.println("Select a type that u wanna make an array of");
system.out.println("1. Player");
system.out.println("2. Team");
Scanner in = new Scaner (System.in);
createArray(in.next());
}
public static void createArray(String **type**)
{
ArrayList<**type**> x = new ArrayList();
}
Is that possible?
Run away from Stringly-typed thinking and simply create your own class to capture all of the information you would want about a player.
public class Player {
// fields, methods to describe a player
}
public class Team {
// fields, methods to describe a team
}
Then, your ArrayList would work as you expect it to.
List<Player> players = new ArrayList<>();
List<Team> teams = new ArrayList<>();
As a side note: your current code structure would only create the list in that method and it wouldn't be available afterwards. If you want it back, you'd have to return ArrayList<Player>, or alternatively, declare it inside of main when you go to use it.
I am pretty sure it is possible with annotations and a custom annotation processor (but probably not a good idea).
Then your code would look like
#StringlyType String type="Player"
and you would would have to write a custom annotation processor that whenever it encounters a #StringlyType annotation creates a class as the other answers suggest.
But What is the Point?
Disclaimer: I have not actually tried any of this; nor do I intend to. So I can not guarantee it works.
There is no reason for doing this:
Generic types are only for compilation time type checking you need to understand this, they are not needed for what you are doing (determining the generic type at runtime).
You can simply do
List objects = new ArrayList();
and proceed to put any type into it but you will obviously have to cast the objects to the correct type before using them after taken out of the list.

What's the difference Between List and List<?>? [duplicate]

Could you help me understand the difference between unbounded wildcard type List and raw type List?
List<?> b; // unbounded wildcard type
List a; // raw type
Along with this can anybody help me understand what is a bounded type parameter list?
List<E extends Number> c;
Here's a summary of the three:
List: A list with no type parameter. It is a list whose elements are of any type -- the elements may be of different types.
List<?>: A list with an unbounded type parameter. Its elements are of a specific, but unknown, type; the elements must all be the same type.
List<T extends E>: A list with a type parameter called T. The supplied type for T must be of a type that extends E, or it is not a valid type for the parameter.
You should really look at Effective Java, Item 23: Don't use raw types in new code.
To use the example from that book, consider the following example... what if you have a collection where you do not care what types of elements are in it. For example, you want to see how many elements are in common between two sets. You might come up with the following:
public static int numElementsInCommon(Set s1, Set s2) {
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
++result;
}
}
return result;
}
This example, while it works, is not a good idea to use because of the use of raw types. Raw types just aren't type safe at all... you could end up modifying the set in a way that is not type safe and corrupt your program. Instead, err on the side of caution and use the type safe alternative:
public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
++result;
}
}
return result;
}
The difference is that you can only add null to a Set<?>, and you CANNOT assume anything about the element you take out of a Set<?>. If you use a raw Set, you can add anything you want to it. The numElementsInCommon method is a good example where you don't even need to add anything and you don't need to assume anything about what is in the set. That's why it's a good candidate for using the ? wildcard.
Hope this helps. Read that whole Item in Effective Java and it will really become clear.
To answer the second part of your question... remember that I said when you use the ? wildcard, you cannot assume anything about the element you take out of the set? What if you do need to make an assumption about the interface of the object you removed from the set. For example, suppose you want to keep track of a set of Cool things.
public interface Cool {
// Reports why the object is cool
void cool();
}
Then you might have some code like this:
public static void reportCoolness(Set s) {
for (Object item : s) {
Cool coolItem = (Cool) item;
coolItem.cool();
}
}
This is not type safe... you need to make sure you passed in a set with only Cool objects. To fix it, you might say:
public static void reportCoolness(Set<Cool> s) {
for (Cool coolItem : s) {
coolItem.cool();
}
}
This is great! Does exactly what you want and is type safe. But what if later you have this:
public interface ReallyCool extends Cool {
// Reports why the object is beyond cool
void reallyCool();
}
Since all ReallyCool objects are Cool, you ought to be able to do the following:
Set<ReallyCool> s = new HashSet<ReallyCool>();
// populate s
reportCoolness(s);
But you can't do that because generics have the following property: Suppose B is a subclass of A, then Set<B> is NOT a subclass of Set<A>. The technical talk for this is "Generic types are invariant." (As opposed to covariant).
To get the last example to work you would need to create a Set<Cool> by casting (safely) every element in the Set<ReallyCool>. To avoid letting clients of your api go through this nasty, unnecessary code, you can just make the reportCoolness method more flexible like this:
public static void reportCoolness(Set<? extends Cool> s) {
for (Cool coolItem : s) {
coolItem.cool();
}
}
Now your method takes any Set that contains elements that are Cool or any subclass of Cool. All of these types adhere to the Cool api... so we can safely call the cool() method on any element
Make sense? Hope this helps.
On your first question, the difference between List and List<?>:
One significant difference between the two is that when you have an wildcard as the type, the type of the Collection is unknown, so the add method will throw a compile time error.
You can still get values out of the List<?>, but you need an explicit cast.
Both cases let us put into this variable any type of list:
List nothing1 = new ArrayList<String>();
List nothing2 = new ArrayList();
List nothing3 = new ArrayList<>();
List nothing4 = new ArrayList<Integer>();
List<?> wildcard1 = new ArrayList<String>();
List<?> wildcard2 = new ArrayList();
List<?> wildcard3 = new ArrayList<>();
List<?> wildcard4 = new ArrayList<Integer>();
But what elements can we put into this objects?
We can put only String into List<String>:
List<String> strings = new ArrayList<>();
strings.add("A new string");
We can put any object into List:
List nothing = new ArrayList<>();
nothing.add("A new string");
nothing.add(1);
nothing.add(new Object());
And we can't add anything (but for null) into List<?>! Because we use generic. And Java knows that it is typed List but doesn't know what type it is exact. And doesn't let us make a mistake.
Conclusion: List<?>, which is generic List, gives us type safety.
P.S. Never use raw types in your code.

How to get an objects string and add this to a string array

I have an ArrayList of my own class Case. The class case provides the method getCaseNumber() I want to add all of the cases casenumber to a String[] caseNumber. I've tried this
public String[] getCaseNumberToTempList(ArrayList<Case> caseList) {
String[] objectCaseNumber = null;
for(int i = 0; i < caseList.size(); i++) {
objectCaseNumber[i] = caseList.get(i).getCaseNumber();
}
return objectCaseNumber;
}
But my compiler complaints about that the objectCaseNumber is null at the point insid the for-loop. How can I manage to complete this?
Well, you need to create an array to start with, and initialize the variable with a reference to the array. (See the Java tutorial for arrays for more information.) For example:
String[] objectCaseNumber = new String[caseList.size()];
Alternatively, build a List<String> (e.g. using ArrayList) instead. That's more flexible - in this case it's simple as you know the size up front, but in other cases being able to just add to a list makes life a lot simpler.
In idiomatic Java, you wouldn't use ArrayList as a parameter type. Use List.
Slightly more overhead, but simpler and more readable code is to accumulate in another List and then convert into an arrray:
public String[] getCaseNumberToTempList(List<Case> caseList) {
final List<String> r = new ArrayList<String>();
for (Case c : caseList) r.add(c.getCaseNumber());
return r.toArray(new Case[0]);
}
In your code it does make sense to insist on ArrayList due to performance implications of random access via get, but if you use this kind of code (and I suggest making a habit of it), then you can work with any List with the same results.
Well, as I think you may have misunderstood Arrays as a primitive type. Arrays in java are objects and they need to be initialized before you access it.

Using ArrayLists as static properties in classes?

struggling a bit with something. I have built a proof of concept and googled but can't find reason.
I am currently trying to use an ArrayList as a static property in a class to store series of entries. The only problem is that everytime I try add to the Totalentries arraylist I get a nullPointerError.
Would appreciate some guidance as to where I am going wrong?
My Class:
import java.util.ArrayList;
public class Competition {
private static ArrayList totalentries;
public Competition(){
}
public void newEntry(){
totalentries.add("an Entry");
}
}
My Test Code:
public class testEntries {
/**
* #param args
*/
public static void main(String[] args) {
Competition myComp=new Competition();
myComp.newEntry(); //Null Pointer comes here!
myComp.newEntry();
myComp.newEntry();
myComp.newEntry();
myComp.newEntry();
myComp.newEntry();
myComp.toString();
}
}
You never instantiated totalentries in your Competition class.
You would need something like:
private static ArrayList totalentries = new ArrayList();
However, note that I would advise against keeping this "static". Otherwise, every "Competition" you create will be sharing the same list of entries, which is likely not what you really want.
Also, declare your types using interfaces, than instantiate with types. You may also want to use Generics here. So even better (and following standard naming conventions):
private List<String> totalEntries = new ArrayList<String>();
You never make an ArrayList. Try this:
private static ArrayList totalentries = new ArrayList();
though it would be better to use generics and get compile-time safety:
private static ArrayList<String> totalentries = new ArrayList<String>();
Since this list holds properties you wouldn't want it to be replaced so it would be even better if you were to define it like this:
private static final ArrayList<String> totalentries = new ArrayList<String>();
Really, though, none of these are good ideas because you could have multiple instances of your class changing totalentries at the same time. If that is your intent, that multiple Competitions use the one static totalentries for storage then you are better off keeping track of that data in a separate class.
If you are only using one Competition at a time then remove the static keyword.
totalentries is not initialized and it points to null. Make it like this:
private static List<String> totalentries = new ArrayList<String>();
The list must be created prior to usage, try
totalentries = new ArrayList();
You should also use List instead for the totalentries variable instead to allow exchanging te ArrayList with for example LinkedList.

Adding elements to an array?

here i am trying to add elements to the array.
the elements i am trying to add are text fields, so im basically trying to store persons contact details within the array list?
any help would be greatful
public void addContact()
{
ArrayList<String> details = new ArrayList<String>();
{
details.get(txtname(0));
details.get(txtnum(1));
details.get(txtmob(2));
details.get(txtadd1(3));
}
}
It sounds like you haven't thought out the entire problem yet.
Adding elements to an ArrayList in Java is done like this:
public void addContact(){
ArrayList<String> foo = new ArrayList<String>();
foo.add("HELLO");
foo.add("WORLD");
}
yankee2905 explains it very well; that's what you need to get your code to work with an ArrayList.
As a side note, you're not dealing with an array, you're dealing with an ArrayList. For an array, you might have something like this:
String[] details = new String[4];
details[0] = "First";
details[1] = "Second";
details[2] = "Third";
details[3] = "Last";
It almost sounds like you're trying to use an ArrayList to store contact information for multiple people. If that is the case, you will probably want to do it a bit differently. You can create a Contact object that has members for each piece of information you want to store (e.g. firstname, lastname, phone, mobile, address1, address2, etc). Then you can just add Contact objects to your ArrayList like:
Contact contact1 = new Contact();
contact1.setFirstname("Bob");
myArrayList.add(contact1);
public void addContact()
{
ArrayList<String> details = new ArrayList<String>();
{
details.add(//Insert value from post here);
details.add(//Insert value from post here);
details.add(//Insert value from post here);
details.add(//Insert value from post here);
}
}
I've not used java in a while maybe someone will add to this.
You need set or add, not get. See the docs here.
And to get the text from the textfields, use getText.
So you'd have something like:
myArrayList.add(myTextField.getText());
You are trying to use inbuilt array initializer syntax. That does not work on container classes (unless its some new fangled way in c#) you need to use details.add() (or the appropriate member function).
The syntax you are trying to use is for the language supported hardwired array types. In C++ this would look like char x[6] = {'h','e','l','l','o'};. However a container is not an array its a container object. Container objects often mimic arrays by overloading operator[] however they use different data structures behind the scenes -- i.e., they do not use contiguous regions of memory.
p.s., If this was c#.NET -- which I initially assumed -- there is a new mechanism to map array initialization to container object creation. I'll leave it down there for anyone that is interested.
in C# 3.5 using array initializer syntax you can do the following :
public void addContact()
{
ArrayList<String> details = new ArrayList<String>()
{
details.get(txtname(0)),
details.get(txtnum(1)),
details.get(txtmob(2)),
details.get(txtadd1(3))
}
}
Gotta love Microsoft and C# :P
public void addContact()
{
ArrayList<String> details = new ArrayList<String>();
details.add(txtname.getText());
details.add(txtnum.getText());
details.add(txtmob.getText());
details.add(txtadd1.getText());
}
Sorry I don't have an IDE open, but I think this is closer to what you are after.
I think this is the best solution if you want to create an array with some elements:
String[] images = {"a.png","b.png","c.png"};
or
String[] images;
images = new String[]{"a.png","b.png","c.png"};

Categories