Hey guys I just have a quick question about initializing an arraylist
This is just a small piece of code I'm doing
public class OrderManager {
ArrayList<Order>orders = new ArrayList<Order>();
public OrderManager() {
}
public OrderManager(ArrayList<Order> orders) {
orders = new ArrayList<Order>();
}
using a variable orders, and then declaring orders = new correct? Or is this going to be two different instances and when I try to add things to it its not going to work?
Or since OrderManager is going to take an arraylist does it even make sense?
I haven't tested it yet, I just started writing this code and have ran into this problem before where I couldn't add to the list properly and believe it was because of a error similar to this just checking to try and get it right to start with.
public class OrderManager {
private ArrayList<Order>orders;
public OrderManager() {
this(new ArrayList<>());//call constructor
}
public OrderManager(ArrayList<Order> orders) {
this.orders = orders;
}
.
.
//more methods here for example getters and/or setters for orders
}
This is the proper way. Also consider using List rather than ArrayList cause in future if you want not to be ArrayList and for example be LinkedList you don't have to modify this class. Programming to an interface concept.
So your class would look like:
public class OrderManager {
private final List<Order>orders;
public OrderManager() {
this(new ArrayList<>());//call constructor or doing nothing is another option
}
public OrderManager(List<Order> orders) {
this.orders = orders;
}
public List<Order> getOrders(){
return orders;
}
public void addOrder(Order order){
orders.add(order);
}
}
What you are currently doing is assigning a new, empty ArrayList instead of taking the one given.
You should either do this:
public class OrderManager {
private final List<Order> orders;
public OrderManager() {
orders = new ArrayList<Order>();
}
public OrderManager(final List<Order> orders) {
this.orders = orders;
}
Which will take the reference to the List passed into the constructor. Changes to the List from outside the class will affect the List inside the class.
A more common way is to make a "defensive copy" using the copy constructor
public class OrderManager {
private final List<Order>orders;
public OrderManager() {
orders = new ArrayList<Order>();
}
public OrderManager(final List<Order> orders) {
this.orders = new ArrayList<Order>(orders);
}
Now the class has a copy of the List passed in so it will be independent of the original List.
Your second constructor is wrong.
It should be:
public OrderManager(ArrayList<Order> orders) {
this.orders = orders;
}
Constructor is what used to create a new object and initialize its class variables.
When you use new you are calling a class constructor.
There are cases when one constructor can be called from another. It's done when the calling constructor initializes a larger set of variables and uses other constructor to initialize a sub-set (so not to repeat the same code). At such cases you use this with a proper signature.
Related
This question is an extension of this question.
What if in that question AbcRunnable would have a member variable as a class which only has methods which are getting called from Runnable. E.g.
public class AbcRunnable implements Runnable
{
private final AbcSupplier supplier;
public void run() {
List<Message> messages = supplier.get();
}
}
public class AbcSupplier implements Supplier<List<Message>> {
public List<Message> get() {
List<Message> list = new ArrayList<>();
/*
Some operations on list
*/
return list
}
}
So, in this case, if 2 threads are sharing the object of AbcSupplier because we are creating only one instance of it. Then, will they also share the local variable list in there? Or they won't be?
I tried running it by myself. To me, it looked like, they are getting shared but not 100% sure.
No. Two threads running AbcRunnable.run() won't share the same instance of the list returned by AbcSupplier.get(). This is because get() creates an ArrayList instance every time it runs.
Here's a version that would cause threads to share the same list:
public class AbcSupplier implements Supplier<List<Message>> {
List<Message> list = new ArrayList<>();
public AbcSupplier() {
......
Some operations on list
......
}
public List<Message> get() {
return list;
}
}
In this case, the same AbcSupplier instance would return the same List instance.
I am trying to up create and update an ArrayList by passing an argument, so that I will end up with a list of say 10 names; however, the current function doesn't seem to be working - any ideas pls?
public String addClient(String name) {
ArrayList<String> myList = new ArrayList<String>();
myList.add(name);
return myList;
}
You are creating a new ArrayList every time you call it. This means that every time you call this method you create a brand new Collection and only store the one client in it. You need to keep a reference of a single collection around and keep adding to that. You can do that by passing in the array you want to add it to:
public List<String> addClient(String name, List<String> array) {
array.add(name);
return array;
}
This doesn't seem like a useful function, so I'm guessing this is within a class. So this might be the approach you want:
/**
* Class is not Thread Safe
*/
public class ClientList {
private final ArrayList<string> clients;
public ClientList() {
this.clients = new ArrayList<>();
}
public void addClient(String client) {
this.clients.add(client);
}
public List<String> getClients() {
// Note: Never give a reference to the internal objects of the class
// as that means someone outside this class can own a reference to it
// and can update the object without you knowing (by not going
// through this class)
Collections.unmodifiableList(this.clients);
}
}
This is what you need to do:
ArrayList<String> myList = new ArrayList<String>();
public void addClient(String name) {
myList.add(name);
}
If you create a list inside the method, it will only have one value, and will go away once method execution finishes (unless it's returned). Have a look at different scopes here. You should create a list at a class level and add the elements into it.
Also, method does not need to return anything, so it's better to change the type to void.
The problem with your approach is that everytime you call the method addClient a new ArrayList will be created.
I think this will work for you :
static ArrayList<String> myList;
public static void main(String[] args) {
myList = new ArrayList<>();
}
public void addClient(String name){
myList.add(name);
}
I really feel like there must be a way around this.
Imagine I have a large number of objects as components of an owner class. I want to offer easy access to the clients of this owner class to its members, so I make all those objects public. Each of those objects also have all their members public. But one member of the components should not be accessible to the clients of their owner, only by their owner itself:
public class ComponentObject
{
public int int_field;
public float float_field;
public Object object_field;
public Object public_method1()
{
//something;
}
public Object public_method2()
{
//something;
}
public Object restricted_to_owner_only()
{
//something;
}
}
//all clients of Owner should be able to access all the members of its components, except
//restricted_to_owner_only, which only Owner should be able to access
public class Owner
{
public ComponentObject component1;
public ComponentObject component2;
public ComponentObject component3;
//... lots of others
public ComponentObject component300;
}
Is there a way to achieve this? Note that any class from any package can own a ComponentObject, so using package level visibility at restricted_to_owner_only doesn't seem to be an option. ComponentObject is like a utility class, reusable in other applications.
Maybe there's an annotation that enforces that at compile time in some nice lib out there?
EDIT: I forgot to mention that ComponentObject is a parameterized type in real life, and each field in Owner is parameterized differently. I tried to abstract off the details so we could focus on the design problem itself, but I abstracted too much. I will post bellow something more similar to the real problem:
public class ComponentObject<T>
{
public int int_field;
public float float_field;
public T object_field;
//any method could return T or take T as an argument.
public T public_method1()
{
//something;
}
public Object public_method2()
{
//something;
}
public Object restricted_to_owner_only()
{
//something;
}
}
//all clients of Owner should be able to access all the members of its components, except
//restricted_to_owner_only, which only Owner should be able to access
public class Owner
{
public ComponentObject<String> component1;
public ComponentObject<File> component2;
public ComponentObject<Consumer<Boolean>> component3;
//... lots of others
public ComponentObject<Integer> component300;
}
EDIT 2 (Possibly a solution): Guys, inspired by Romeo and Juliet's love, I wrote this solution, can you spot any faults with it? Or would it work as I intended?
//add this class
public class OwnershipToken
{
private static int id_gen = 0;
public final int id = id_gen++;
#Override
public boolean equals(Object obj)
{
return (obj instanceof OwnershipToken) && ((OwnershipToken)obj).id == id;
}
#Override
public int hashCode()
{
return id;
}
}
//Then change this in ComponentObject<T>:
public class ComponentObject<T>
{
//add this field:
private final OwnershipToken ownershipToken;
//add this constructor
public ComponentObject(OwnershipToken onwershipToken)
{
this.ownershipToken = ownershipToken;
}
//change restricted_to_owner_only signature:
public Object restricted_to_owner_only(OwnershipToken ownershipToken)
{
//add this condition
if(this.ownershipToken.equals(ownershipToken)
//something;
}
}
//finally, Owner gains a field:
public class Owner
{
private final OwnershipToken ownershipToken = new OwnershipToken();
//... etc, remainder of the class
}
would this work as intended?
I understand what you want and that is impossible i think.
But, there is still one way to do it!
Make an id in the owner class:
private int id = new Random().nextInt(10000);
In ComponentObject:
private id;
public ComponentObject(int id){
this.id = id;
}
public Object restricted(int id){
if(this.id != id)
return null;
else
return object;
}
In owner:
private ComponentObject<String> string;
public Owner() {
string = new ComponentObject<>(id);
string.restricted(id);
//if the id is right it will return the restricted object, if not i will
//return null
}
I have an Object named Person(name, surname, age)
This Object is populated with values from a local file.
But i want to keep this object visible through the app since there is a GUI for adding new values to this.
I was trying to put an Interface like this but doesn't work
public interface MyInterface{
public List<Person> myPersonObj = new ArrayList<Person>();
}
and to call it in app like MyInterface.myPersonObj
Can someone help me?
Thanks
You have to declare the variable static, e.g.
public static (final) List<Person> persons = new ArrayList();
For more information, read about the Singelton Pattern
Because it's in an interface it will automatically be final (read-only), thus you probably want to put it in a class instead:
public class AnyClass{
public static List<Person> myPersonObj = new ArrayList<Person>();
}
Then you can do:
AnyClass.myPersonObj
to access it.
make the list static inside the class where you populate it.
class Populate{
public static List<Person> myPersonObj;
public static void setMyPersonObj(List<Person> inst){
myPersonObj =inst;
}
public static List<Person> getMyPersonObj(){
if(MyPersonObj!=null){
return myPersonObj;
}
else {
return new ArrayList<Person>();
}
}
//populate it
}
class SomeOther {
public static void someMethod(){
Populate.getMyPersonObj();
}
}
I would like to know how to be able to invoke the contains method directly on my class instead on its ArrayList variable. Best way to explain is really with the code below.
Thanks for your help.
public class Chord {
ArrayList<Note> notes;
// some more stuff not here
}
cmaj = new Chord("Cmaj");
cnote = new Note("C");
// what I have
cmaj.getNotes().contains(cnote);
// what I would like, is this possible, how?
cmaj.contains(cnote);
Well you can just write the method yourself:
public class Chord {
private final List<Note> notes;
...
public boolean contains(Note note) {
return notes.contains(note);
}
}
This is typical example of proxy methods (see proxy patter).
public class Chord {
private final List<Note> notes = new ArrayList();
public boolean contains(Note note) {
return notes.contains(note);
}
}
When you are using this type of methods, you should double check that reference is set before the object is delivered to client. If you do not pay attention you will get NullPointerException. And Try to stay consistent, if you decide to use contains in that way, add, remove and reset should also be implemented. And then the getter is no more required.
Write a method contains() inside chord that simply delegates the call the the arraylist as below:
public class Chord {
ArrayList<Note> notes;
public boolean contains(Object o) {
return notes.contains(o);
}
}
Add a method contains encapsulating the arrayList´s contains:
public class Chord {
ArrayList<Note> notes;
// some more stuff not here
public boolean contains(Note note){
return notes.contains(note);
}
}