Call methods from a class that is inside an array - java

I have an array with objects inside. How would I use methods on the array element?
My array is of type Object. I tried array[i].getSalary() but this doesn't work.

First of all, you should almost never use an array of Object. The reason is that you lose all type information that :
would make the code more understandable for people who will read your code (including your professor, yourself, and yourself in six months when you will have forgotten everything about the code)
could be used by the compiler and your IDE to tell you when you are doing mistakes even before you test the program.
would avoid the type of error-prone casting that I am going to explain to you in the second part of this answer.
Instead of an array of Object, use an array of the type corresponding to the types of the object that will be put inside it (or a common base class). Assuming that your class is called Employee, you should declare your array this way:
Employee[] employeeArray;
(employeeArray is a better name than array because it tells what kind of objects it contains, again for readability. In general, prefer explicit names for variables.)
With that solution it is easy to use employeeArray[i].getSalary(), if the class Employee contains such method. The intention of this code is also obvious when you read it.
Other possibilities are generic collections like List<Employee> or Set<Employee>, depending on your needs.
If you really have to use an array of Object, and call a getSalary() method, you will have to cast the array elements to the class or interface to which the method getSalary() belongs.
For example and again, if this class is called Employee:
Employee employee = (Employee) array[i];
employee.getSalary();
What casting does is obtaining a reference of type Employee of your object. The object is still the same but now you can call methods of Employee on this object.
But this solution have a number of caveats. First, it is more verbose and it takes two lines to make what could have taken just one. Second, and more importantly, since you have an array of Object, you can not be certain that you really have an object of type Employee, and if it is not the case, the operation will throw a ClassCastException. A solution to this is to first check that the object is really of the desired type:
Object object = array[i];
if (object instanceof Employee) {
Employee employee = (Employee) object;
employee.getSalary();
}
else {
System.err.println("Object is not an Employee: we can not call getSalary()!");
}
But you see that it becomes much more verbose and if you multiply this by the number of times you will have to call a method of these objects, then the code becomes unmanageable.

Do all your objects inside your object[] have the getSalary() method?
If not, then you can obviously see why the compiler doesn't let you do that. There's something funny going on somewhere in your code if you end up in this situation.
If yes, is it either the very same getSalary() method or multiple dynamically bound implementations of the same method in the same class hierarchy?
If neither, you should probably make an interface IHasSalary (lame name, I know) that exposes such a method, make all these objects implement that interface, then declare the array as IHasSalary[].
If yes, find their most specialized common ancestor, say it's the class Employee, and declare the array as Employee[].

Related

How does ArrayList.get return its objects?

Context: I'm making a mini-interpreter-ish calculator thing. I figured that the best way to hold the symbol table was to make an ArrayList of an Object that I've defined (name of the object is WiP). Setting up the ArrayList looks like.
ArrayList<miniVariable> vList = new ArrayList<miniVariable>();
Simple enough, and the miniVariable Object contains the following variables
public String name;
public double value;
public boolean initialized;
They are public because I already made setter/getters in the class with the ArrayList, when I didn't realize you could make one of Objects, and I don't want to move everything over. I probably should.
Question: If I were to call vList.get(index) .value = 5; would it actually change the value being stored in the vList(index)'s value variable? Or does .get(index)just return a copy of the data, and so changing this copy doesn't actually do anything?
It changes the value on the original instance, as one would expect.
Creating a copy of an object in Java only happens explicitly (and usually with some difficulty at that).
A few other notes:
Class names in should be CapitalCase.
Implementing getters and setters on an object holding a list of objects is bad practice as it violates encapsulation. If you're implementing getters and setters, it's best to put them on the class they apply to.
What you are storing in the ArrayList is not the object itself, but reference to object.
So when you do vList.get(i) it is returning you the reference that you previous put in. Which means you are going to access the same object that you previous put in the list, instead of a copy of it.
Get yourself familiar with one of the basic concept of Java, which is Reference and Primitive types.
Some off-topic suggestions:
Make sure you are aware of Java's naming convention. For example, for the class name, it should be MiniVariable instead of miniVariable.
Just to be more accurate: "and the miniVariable Object contains the following variable", MiniVariable is a class, but not an object. You may say "and a MiniVariable object (instance) contains these member fields", or "in MiniVariable class defined the following member fields"
All collections objects stores reference to object , if you change any thing on object directly(accessing through collection) or indirectly ( already have reference of it) it will change the state of the object stored in collection

Cast to type which is not inherited

I have class lets say
public class Magic implements Serializable{
}
and this class does not inherit
public class Amount{
}
Is there any way to cast Magic to Amount, I will be not accessing any fields what so ever, i just need Magic to "become" Amount? Is there any way?
No there isn't. An instance of Amount is unrelated to an instance of Magic.
This is true even if the two classes look identical, which in your case they certainly are not.
In this case, you need to suffer the pain of writing the code to convert Magic to an Amount. Perhaps have a constructor in Amount that takes a Magic instance as the parameter.
Alternatively, if Amount contains only functions, then consider recasting it as an interface, which is implemented by Magic.
You can't cast between unrelated types in Java. If you need to create an Amount instance from a Magic instance you should have a constructor that receives such an argument:
public class Amount {
public Amount(Magic m) {
// Initialize amount's fields...
}
}
Casting does not automatically convert objects from one type to another type.
A cast is a way to disable the compiler's type checks. The only thing that a cast does, is tell the compiler: "Here is an object, and I know better than you what kind of object this is, so I want you to treat it as an object of this type, and not complain".
A type check will still be done, at runtime, and if at that time the object really is not of the type that you said it was, you will get a ClassCastException.
A cast cannot automatically convert a Magic object into an Amount object.
You need to write the code yourself to create an Amount object using the data of the Magic object.
The only way to have Magic become Amount is to have your class: Magic extend the Amount class.
You want an is a link between classes and this is done by inheritance.
Otherwise you will receive a compilation error.

Object list within an object

I have created an object that contains an Arraylist and that Arraylist contains objects. My question is, how do i point to the objects in the Arraylist?
the original Object contains:
some attributes,
list = new arraylist
The List contains:
14 objects of similar data
This seems like a fairly simple task, but because you did not give me your exact code, I am just going to assume.
Let's say this is the class of the object that you were talking about
public class ClassA {
public ArrayList<Integer> list = new ArrayList<>(); //I guess integers are "similar data"
}
Now you have that object, called obj
ClassA obj = new ClassA ();
You can just access the array list by doing this
obj.list
For example you can add an item to the array list like this:
obj.list.add(10);
And you can retrieve the first item
obj.list.get(0);
Easy!
If you think you understand little of the above, I'll explain. If you think you understand it completely, you can just accept the answer and go.
Almost every class declare members. And so does your class, ClassA. Any accessible member can be accessed using .. We call it the dot operator.
And what is an accessible member?
Different access modifiers provide different accessibility, read this to find out more: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html In the above example, list is a member, and it is declared public This means that it is accessible everywhere.
This is why you can access it using ..
Actually, I think you must have used this technique before! When you call
System.out.println ("Hello World");
You use the dot to access members!
In the System class, there is a member called out. out is of type PrintStream. In PrintStream class, there is another member called println! See? that's how Java works.
If you still don't understand, read this part again. If you understand, please click that green tick to accept the answer.

In java , can we pass superclass Object to subclass reference?

In java, can we pass superclass Object to subclass reference ?
I know that it is a weird question/practically not viable,
but I want to understand the logic behind this
Why is it not allowed in java.
class Employee {
public void met1(){
System.out.println("met1");
}
}
class SalesPerson extends Employee
{
#Override
public void met1(){
System.out.println("new met1");
}
public void met2(){
System.out.println("met2");
}
}
public class ReferenceTest {
public static void main(String[] args) {
SalesPerson sales = new Employee(); // line 1
sales.met1(); // line 2
sales.met2(); // line 3
}
}
What would have happened if Java allowed compilation of line 1?
Where would the problem arise?
Any inputs/link are welcomes.
If your SalesPerson sales = new Employee(); statement was allowed to compile, this would have broken the principles of Polymorphism, which is one of the features that the language has.
Also, you should get familiar with that does compile time type and runtime type mean:
The compile-time type of a variable is the type it is declared as, while the runtime type is the type of the actual object the variable points to. For example:
Employee sales = new SalesPerson();
The compile-time type of sales is Employee, and the runtime type will be SalesPerson.
The compile-time type defines which methods can be called, while the runtime type defines what happens during the actual call.
Let's suppose for a moment that this statement was valid:
SalesPerson sales = new Employee();
As I said, the compile-time type defines which methods can be called, so met2() would have been eligible for calling. Meanwhile, the Employee class doesn't have a met2() and so the actual call would have been impossible.
No. It makes zero sense to allow that.
The reason is because subclasses generally define additional behavior. If you could assign a superclass object to a subclass reference, you would run into problems at runtime when you try to access class members that don't actually exist.
For example, if this were allowed:
String s = new Object();
You would run into some pretty bad problems. What happens if you try to call a String method? Would the runtime crash? Or perhaps a no-op would be performed? Should this even compile?
If the runtime were to crash, you could use runtime checks to make sure the objects you receive will actually contain the methods you want. But then you're basically implementing guarantees that the Java type system already provides at compile-time. So really that "feature" cost you nothing but a bunch of type-checking code that you shouldn't have had to write in the first place.
If no-ops were executed instead of nonexistent methods, it would be extremely difficult to ensure that your programs would run as written when the members you want to access don't exist, as any reference could really be an Object at any point. This might be easy to handle when you are working on your own and control all your code, but when you have to deal with other code those guarantees essentially vanish.
If you want the compiler to do the checking, assuming compiler writers don't hunt you down and give you a stern talking-to -- well, you're back to "normal" behavior once more. So again, it's just a lot of work for zero benefit.
Long story short: No, it's not allowed, because it makes zero sense to do so, and if a language designer tried to allow that they would be locked up before they could do any more harm.
If you inherit from a class, you always specialize the common behavior of the super class.
In your example, the SalesPerson is a special Employee. It inherits all behavior from the super class and can override behavior to make it different or add new behavior.
If you, as it is allowed, initialize a variable of the super type with an instance of the sub type like Employee e = new SalesPerson(), then you can use all common behavior on that variable.
If instead, you were possible to do the other way round, there might be several uninitialized members in the class.
You find this very often when using the Java Collection API, where for example you can use the common List class on operations like iterating through it, but when initializing it, you use for example the sub class ArrayList.

Detect Object type then cast it accordingly?

My method takes as input an Object. How do i determine it's type, then cast it accordingly?
So for example: binarySearch( Object o );
Inside the binarySearch method, i need a way to determine the type (or class) of Object o. Then i need to cast it with that type. how would i do that???
And more specifically, Object o is a child of a base class (EG SalariedEmp is child of Employee), and i specifically need the base class.
EDIT:
I figured out how to do what I wanted, which really should be a completely different question. I needed to use the .compareTo method from Comparable to set up a way to compare two objects based on private data from those objects. All i had to do was implement my class as 'Comparable' using the implements keyword. So no matter what Type of objects are compared in my binarySearch method, it works if they are of the same (unknown) type and have Comparable implemented. This makes my binarySearch method very re-usable with any type of comparable class.
So, in all fairness, I'll accept the answer that covers the original question.
:)
Two ways to do this:
Use the instanceof operator.
Call getClass() on the object (make sure to check for null first).
if (o instanceof SalariedEmp)
doSomethingWith((SalariedEmp)o);
You can use RTTI (Run-Time Type Identification) by using the instanceof operator or by calling .getClass() on the instance, but that's almost always an indication that the super-type you're using is either the wrong super-type, or is badly designed.
In your case, you don't need to be using Object, as you already know that you at least have an Employee.
The Object Oriented paradigm is that you don't ask an object instance what it is, you ask it to do something. In this case, you have a choice of several thing you might want to ask an Employee object to do. Which one is the best choice for you depends on exactly what you're trying to model:
You could ask it if it is salaried, and then possibly cast it, by adding a virtual method boolean isSalaried() to the Employee base class. The base method would return false, but a SalariedEmployee would override that method and return true.
But while that avoids (the likely more expensive) RTTI, it doesn't avoid the cast. You could add a method SalariedEmployee asSalariedEmployee(), which in the base class would return null and in a SalariedEmployee would return this. That gives you a "safe" cast, but you still need a test against null.
Or you could just add a Money getSalary() method to Employee. Now you don't have to do any casting, but you'd need to decide what the salary of a non-salaried employee is; that could be null, zero, or NaN (the special Not a Number value).
If you decided to return null, in some cases (e.g, adding values) you'd have to test against null, in others (e.g, passing the salary to .equals()) you wouldn't need to test against null, as any instance.equals(null) should return false by the specification for Object.equals().
If you return zero, you can add without testing against null, but equals might be a bit weird -- is it really true that two hourly workers, each of whom get no salary, have the same (nonexistent) salary? That depends on what you're modeling. If it is true, return zero.
If it's not true that two hourly workers have the same non-existent salary, return a NaN value. This is justa specific case of the "Null Object Pattern".

Categories