Allow an ArrayList to be used in different classes - java

If I create a class that reads text into an ArrayList. How do I access this ArrayList in other classes? What do I declare the ArrayList as in the class?
Then when I want a different class to access it, how do I go about doing that? I have tried making it static but I still don't know how to access it in other classes.

Declare it as a member e.g.
public class A {
public final List<MyObj> list = new ArrayList<MyObj>();
}
and then
A a = new A();
a.list; // there you go
(note that I've declared it as a List, rather than an ArrayList. That's an implementation issue, and I could simply choose to expose it as a Collection. It's also marked as final since I don't want to change it inadvertently. I can revert that decision later if need be).
It is preferable to make it private and access it via an accessor e.g.
public class A {
private final List<MyObj> list = new ArrayList<MyObj>();
public List<MyObj> getList() {
return list;
}
}
A a = new A();
a.getList();
although someone external to your class could modify it (!). So you could copy it prior to exposing it, or wrap it using Collections.unmodifiableList().
It is better still to hide it completely and ask class A to do something for you (which may involve that list - that's an implementation detail)
public class A {
private final List<MyObj> list = new ArrayList<MyObj>();
public void doSomethingForMe() {
for (MyObj obj : list) {
// do something...
}
}
}

Add a public getter for your list in the class containing it. In the class you want to use the list in, create an instance of class containing the list and get the list by calling the getter method.
class A {
List<String> list = new ArrayList<>();
public List<String> getList() {
return list;
}
}
Class B {
public vois useClassAList() {
A a = new A();
List<String> list = a.getList();
// do what ever you want with the list
}
}

You could return the ArrayList from the class using a get method.
public class A{
//....
public ArrayList<String> getArray(){
return listToReturn;
}
}
therefore you'd only have to call the method and your variable doesnt have to be static:
A a = new A();
a.getArray();

Related

Add some properties for each ArraList entry

I want to use ArrayList for example but besides only keeping an entry I want to store additional information: "write-in" time, some flag maybe. I could extend the class I am going to store but I want it to be the list feater. I thought maybe to do something like
public class PropertirizedArrayList<E> implements List<E> {
private static class TupleContainer<E>{
public E mainValue;
public Long hidingTime;
public Boolean flag;
}
private ArrayList<TupleContainer<E>> list = new ArrayList<>();
private ArrayList<TupleContainer<E>> delegate(){
return list;
}
//etc...
}
but I think it would be a great problem to reimplement all the List interface methods.
You can simply use List<TupleContainer<SomeType>>. I don't see a need to wrap the List with PropertirizedArrayList.
And if you do have some good reason to use a wrapper class (such a reason would be additional features that your wrapped list implements), you don't have to re-implement the existing List methods.
You have a List member contained within your class, so you can delegate each method of your class to the list.
For example :
public TupleContainer<E> get (int index)
{
return list.get (index);
}
Or if you don't want to expose TupleContainer :
public E get (int index)
{
return list.get (index).mainValue;
}
try this ...
private class TupleContainer<E>{
public E mainValue;
public Long hidingTime;
public Boolean flag;
}
List<TupleContainer<YourType>> list=new ArrayList<TupleContainer<YourType>>();
TupleContainer<YourType> tc=new TupleContainer<YourType>();
tc.mainValue=value;
tc.hidingTime=value;
tc.flag=value;
list.add(tc);

java: how do I stop people from clearing my arraylist<string> When I use a getter method?

I have declared my arraylist in class A:
private ArrayList<String> user = new ArrayList<String>();
I have created my getter method in the same class (Class A):
public ArrayList<String> getUser()
{
return user;
}
Then in my second class (Class B) I am able to do the following:
A UD = new A();
UD.getUser().clear();
UD.getErrmsg().clear();
how do I prevent my second class from clearing the arraylist in my first class (class A)?
There is a method for this in the Collections class you can use: return Collections.unmodifiableList(user); There are various other methods you might need, including ones for maps and so forth. Just take a look at the documentation.
Solution for both the getter and the setter:
public void setMyList(final List<String> list)
{
myList = new ArrayList<>(list);
}
public List<String> getMyList()
{
return Collections.unmodifiableList(list);
}
Using Guava:
public void setMyList(final List<String> list)
{
myList = ImmutableList.copyOf(list);
}
public List<String> getMyList()
{
return list;
}
If you can afford it, use Guava.

Java Converting List<Vehicle> to List<Object>

My applications consists of Vehicle class and Customer class where I have an interface to add delete and search for each.
Because of this I implemented my interface for add as follows:
public void add(Object newObject, List<Object> myList);
and therefore this accepts all objects. However when I am trying to pass a Vehicle list from my application I am getting an error as it is expecting an Object List. How can I convert my List to List and still update the lists.
This is my initialized list of allVehicles.
List<Vehicle> allVehicles = new ArrayList<Vehicle>();
This is the method I am using to add new Vehicle where I am getting the error on allVehicles.
addNewCycle.add(addNewCycle, allVehicles);
The method from the Vehicle class implemented from interface.
public void add(Object newObject, List<Object> myList) {
myList.add((Vehicle)newObject);
}
My question is how can I cast this list to an Object list and update it on Vehicles List.
Consider using generics for your interface
public interface Adder<T> {
public void add(T newObject, List<T> myList);
}
Then you can do this
public class Vehicle implements Adder<Vehicle> {
#Override
public void add(Vehicle newObject, List<Vehicle> myList) {
myList.add(newObject);
}
}
Try this.
List<Vehicle> allVehicles = new ArrayList<Vehicle>();
// add some vehicles
List<Object> allVehicles1 = new ArrayList<Object>();
allVehicles1.addAll(allVehicles);
// now use allVehicles1
Converting the Vehicle into Object is really futile. A better option would be redesigning your interface to support generics for add method:
public <T> add (T data, List<T> list);
In this case, your class can easily support this:
interface Foo {
public <T> boolean add(T data, List<T> list);
}
class Bar implements Foo {
#Override
public <Bar> boolean add(Bar data, List<Bar> list) {
return list.add(data);
}
}
public class TestBar {
Bar bar = new Bar();
List<Bar> list = new ArrayList<>();
bar.add(bar, list);
//prints the elements in the list
//override toString method in Bar for a "nicer" result
System.out.println(list);
}
A better implementation would be:
class Adder implements Foo {
#Override
public <T> boolean add(T data, List<T> list) {
//totally generic
return list.add(data);
}
}
the Collection are by default Objects but since 1.5 Sun adds new mechanism to deal with objects called Generics. In other words
If you write
ArrayList arr =new ArrayList();
without the generics it will work. Objects and this words for < 1.4
If you have
List<Vehicle> allVehicles = new ArrayList<Vehicle>();
and you wanna transfer it to ArrayList of Objects
List noremalArray = new ArrayList(allVehicles);

Generic return type when using reflection to invoke a method

First, read the code below.
I want to call the invoke method of the SuperClass, without having to cast the return value to the corresponding type.
The problem is that the SuperClass implementation is located one project and the SuperClassImpl1 and 2, are in another project.
In runtime these are in different classloaders, i.e. ClassLoader 1 knows about SuperClass but not about SuperclassImpl1. I have a "SuperClassLoader" which gives ClassLoader 1 a class object of e.g. SuperClassImpl2, but I can only use it as a SuperClass object.
Right now my code looks like the one below, and i have to cast it to e.g. a Map if i know that the method name I give to invoke returns a Map.
What I would want is that depending on the return type of the method given by the methodName, the return type of the invoke method should change accordingly.
E.g. invoke("getMyMap") should return a Map. Note, I dont want this:
Map m = invoke("getMyMap");
m.get(...);
I want this:
invoke("getMyMap").get(...);
Is it possible?
public abstract class SuperClass(){
public Object invoke(String methodName){
Method method = this.getClass().getDeclaredMethod(methodName);
return method.invoke(this);
}
}
public class SuperClassImpl1() extends SuperClass{
Map<String,String> myMap;
public SuperClassImpl1(){
myMap = new HashMap<String,String>();
}
public Map<String,String> getMyMap(){
return myMap;
}
}
public class SuperClassImpl2() extends SuperClass{
List<String> myList;
public SuperClassImpl2(){
myList = new ArrayList<String>();
}
public ArrayList<String> getMyList(){
return myList;
}
}
public class MainClass(){
public static void main(String[] args){
SuperClass mySuperClass1 = new SuperClassImpl1();
SuperClass mySuperClass2 = new SuperClassImpl2();
System.out.println("Something in my map: "+mySuperClass1.invoke("getMyMap").get("Some value"));
// something similar using mySuperClass2 here...
}
}
The problem is that, in the definition of invoke(), the return type is always an object. This is just the way things are.(documentation)
If you want to use reflection, you will have to use casting at some point. You could create a wrapper method that does the casting for you, but there is no getting around it.
The way I got it to work was like this:
System.out.println("Something in my map: "+((Map<?, ?>) mySuperClass1.invoke("getMyMap")).get("Some value"));
The return type of the method can not depend on the String that you pass to it, because the type is resolved at compile time while the argument is only known at run time.
You can, however add parameter to your classes.
public abstract class SuperClass<T> {
public T invoke(String methodName){
Method method = this.getClass().getDeclaredMethod(methodName);
return (T) method.invoke(this);
}
}
public class SuperClassImpl1() extends SuperClass<Map<String, String>> {
...
}
public class MainClass(){
public static void main(String[] args){
SuperClass<Map<String, String>> mySuperClass1 = new SuperClassImpl1();
SuperClass<ArrayList<String>> mySuperClass2 = new SuperClassImpl2();
System.out.println("Something in my map: "+mySuperClass1.invoke("getMyMap").get("Some value"));
// something similar using mySuperClass2 here...
}
}
You can't do it because generic types are checked at compile time, and the actual return type of the methods you invoke is not known until run time.
Map m = invoke("getMyMap"); // checked at compile time
return method.invoke(this); // resolved at run time

Extending ArrayList and Creating new methods

I'm having a bit of a problem grasping something - I might be going about this completely wrong.
I am trying to create a class which extends ArrayList but has several methods which increase the functionality (at least for the program I am developing.)
One of the methods is a findById(int id), which searches each ArrayList object for a particular id match. So far it's working, but it won't let me do for (Item i : this) { i.getId(); }
I don't understand why?
Full code:
public class CustomArrayList<Item> extends ArrayList<Item> {
// declare singleton instance
protected static CustomArrayList instance;
// private constructor
private CustomArrayList(){
// do nothing
}
// get instance of class - singleton
public static CustomArrayList getInstance(){
if (instance == null){
instance = new CustomArrayList();
}
return instance;
}
public Item findById(int id){
Item item = null;
for (Item i : this) {
if (i.getId() == id) {
// something
}
}
return item;
}
public void printList(){
String print = "";
for (Item i : this) {
print += i.toString() + "\n";
}
System.out.println(print);
}
}
Change
public class CustomArrayList<Item> extends ArrayList<Item> {
to
public class CustomArrayList extends ArrayList<Item> {
I suspect Item is the name of the class that you want to store in the list. By adding <Item> after CustomArrayList you're introducing a type parameter which shadows this class.
With the <Item> parameter, your code is equal to
public class CustomArrayList<T> extends ArrayList<T> {
// ...
for (T i : this) { i.getId(); }
// ...
}
which obviously won't always work, as T may refer to any type.
What is getId()? Presumably it's a method in some class, but we don't know which class.
If you've actually got a class called Item with a getId() method, which this is meant to be a list of, you simply need to stop your class from being generic. So instead of this:
public class CustomArrayList<Item> extends ArrayList<Item> {
you want:
public class CustomArrayList extends ArrayList<Item> {
Currently within your class, Item doesn't refer to a class called Item, it refers to a type parameter called Item.
Now personally:
I wouldn't avoid creating singletons unless you really have to
If you have to, I'd avoid creating them in the way you have (which isn't thread-safe)
I wouldn't extend ArrayList<> unless I really had to, preferring composition over inheritance

Categories