Is there a way to cast an Object array into a java class?,
Example: I have a class "Person" with the next attributes: Name, age, address. And i have an Object[] with this: [1]: "Peter", [2]: 20, [3]: "California 130".
I want to do something like this:
Person p = new Person();
Object[] o = new Object[2];
p = (Person) o;
I have to do this without set the values one by one, example:
p.setName((String)o[0]);
Is there a way?
Regards
You're trying to have the compiler convert an array of Object automagically into a a class with fields, and this just isn't possible. Instead you could create a constructor that takes an array of object and then assigns each item in the array into the fields of your class, but while this can be done, it has a bad code smell. Better to avoid use of Object arrays entirely, that is, arrays that hold items of different types. Instead deal with fields and parameters that have appropriate and actual types, and pass correctly typed items into your class's constructor. i.e.,
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
try something like this:
Person convert(Object[] o){
String name = (String) o[0];
int age = (int) o[1];
String address = (String) o[2];
Person p = new Person(name, age, address);
return p;
}
this method asks for this Object[] and returns a person with the information.
You cannot do it, as this would cause ClassCastException to be thrown. The reason is that because of inheritance and the is-a relationship.
Every Person object is an Object and every String object is of type Object. However, the opposite is not true. This is like saying every horse is a mammal, but not every mammal is a horse.
Create a method in the person class (setAttributes(Object[])for example) that sets the person attributes from the array values.
Related
I am having a problem with a class I am writing for an assignment. I have an interface, Person, that has 3 abstract methods getID, getFirstName, and getLastName. These return Strings. I have another class called Employee which implements Person. I have a static method, which takes in a line from a file as a String and instantiates a new object of Employee then returns it as a Person. The only problem is that Employee also has an attribute called salary that Person cannot have, so later when I try to manipulate data on the new objects, I cannot access the salary attribute in the objects. I really don't know any way around this. If any of you can give me any suggestions on this, it would be greatly appreciated. Below you can find the parse method, and the stream I used to create the list, the stream where I attempted to manipulate the salary data, and the interface.
public static Person parse(String s) {
String[] empData = s.split(",");
Employee hello = new Employee(empData[0], empData[1], empData[2], BigDecimal.valueOf(Double.parseDouble(empData[3])));
return hello;
}
List<Person> stream = Files.lines(Paths.get(fileName))
.map(Employee::parse)
.collect(Collectors.toList());
DoubleSummaryStatistics total = stream.stream().mapToDouble((emp) -> Double.parseDouble(emp.salary.toString())).summaryStatistics();
System.out.println("Total average and the total number of employees:");
import java.math.BigDecimal;
public interface Person {
public String getID();
public String getFirstName();
public String getLastName();
}
which takes in a line from a file as a String and instantiates a new object of Employee then returns it as a Person.
Doctor, it hurts when I press here!
Well, stop doing that then.
Return this as a List<Employee> instead. The whole point of returning List<Person> is that you are free to change your mind later and return non-employees (you have signed up to always return persons, but not neccessarily employees), therefore, javac will not let you presume that they are employees. If you want to carry on and assume: Hey, these are always employees, therefore 'person.getSalary()' is always going to be sensible, then... say that.
If you can't, you can use instanceof to check if a person is an employee, and then cast to get the salary:
double salary = p instanceof Employee ? ((Employee) p).getSalary() : 0.0;
and starting in java15, you can write:
double salary = p instanceof Employee e ? e.getSalary() : 0.0;
which is a lot prettier...
but that's a very different kind of code: That's saying: For all persons, IF they are employee, consider their salary to be whatever the employee object says it is. If not, then count them at 0. If that's what you WANT, this code works, but it sounds more like you're confused. Do you have a list of persons, or a list of employees, which one is it?
EDIT: Thanks for all the answers! I didn't know that the object p in List.java is different from the p in Main.java. I passed it as a parameter and it works fine now. Thank you!
In Main.java:
System.out.println("Enter your name:");
String name = scan.next();
name+=scan.nextLine();
String words[]=name.split("\\s");
String capitalizeWord="";
for(String w:words){
String first=w.substring(0,1);
String afterfirst=w.substring(1);
capitalizeWord+=first.toUpperCase()+afterfirst+" ";
}
Person p = new Person(capitalizeWord);
In Person.java
private String name;
private int age;
Person(String newName){
name=newName;
}
Person(int newAge){
age=newAge;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
In List.java:
public void printInvoice(){
System.out.println("Enter your age:");
int age = scan.nextInt();
Person p = new Person(age);
System.out.println("Thank you for shopping with us, "+p.getName());
}
The last output is
Thank you for shopping with us, null
I don't know why this is happening. Did I do something wrong? I think the code is correct?
Each time you call a constructor you get a distinct instance of the object. The object created in Main.java with a name is stored in a local variable p that is only existing in the scope of Main.java. In List.java you create a second object with an age, but no name. It's also stored in a variable called p but that one is in the scope of List.java only and has nothing to do with the earlier created object.
It sounds like you want to add the name to the earlier object and not create a new one. For that you should pass the first object as a parameter to the code that adds the age, perhaps like this:
public void addAge(Person p) {
System.out.println("Enter your age:");
int age = scan.nextInt();
p.setAge(age); // will have to make this method in the Person class
System.out.println("Thank you for shopping with us, "+p.getName());
}
Calling Person p = new Person(age); gives a brand new Person object that has no name yet.
You have two constructors. One that accepts a string, one that accepts a number.
In your latest example you called the one that accepts a number and, since there's nothing initializing the name member, it gets initialized to null as default.
The p in Main.java has nothing to do with the p in List.java (they're two different variables), so initializing the former will have no effect on the latter.
As I can see in your List.java class, you have instantiated a new Person object with age as a parameter, so for that object, the name would be null, since the two reference variables are pointing to the different Person object
The first reference p to object Person has instantiated the person object using the contructor:-
Person(String name) {
this.name = name;
}
Second reference p to object Person has instantiated the person object using the constructor:-
Person(int age) {
this.age = age;
}
You should have used setter to set the property age to an already created Person object
code that create your person -> Person p = new Person(age);
constructor called -> Person(int newAge){
age=newAge;
}
This constructor let the name with his default value.. so null
I'm starting to learn java, and faced this problem when I can reach object name and lastName, but can't reach if I put them in object array.
public class Human {
String name;
String lastName;
String[] people;
People(String name, String lastName) {
this.name = name;
this.lastName = lastName;
};
public static People tom = new People("Tom", "Tommy");
public static People ted = new People("Ted", "Teddy");
public static Object[] objects = {
tom,
ted
};
public static void main(String[] args) {
System.out.println(tom.lastName);
System.out.println(objects[0]);
and this line I need does not work.
System.out.println(objects[0].lastName);
}
Simple: you declared that array of type Object.
Objects don't have names, only an instance of People has!
In other words: you want to declare an array of People, not Object.
You see, the compiler only "remembers" the type that is used on the left hand side of that variable declaration. It does not know that you in fact created an array of Object and placed solely instances of People inside that array.
And unrelated: people implies plural. You should rather call that class Person, or maybe PersonInfo.
Here, Object[] objects is an array of Object and Object class does not have anything like lastName. There is two way to solve the problem.
Declare the array as People[] objects
or
Cast the object to people like ((People)objects[0]).lastName
I missed one of my lectures in Java, and the subject was classes, methods, constructors etc. The homework is one task:
Create a class Person, objects of which describe persons, and which
contains only two felds: name (String) and year of birth (int). In
this class, define
constructor taking name and year of birth;
constructor taking only name and setting the year of birth to default value 1990;
method isFemale returning true if this person is a woman (we assume, not very sensibly, that only women and all women have names ending
with the letter 'a'); otherwise the method returns false;
static function getOlder taking two references to objects of class Person and returning the reference to the older of these two persons;
static function getOldest taking the reference to an array of references to objects of class Person and returning the reference to
the oldest person represented in the array;
static function getYoungestFemale taking the reference to an array of refe- rences to objects of class Person and returning the reference
to the youngest woman represented in the array, or null if there is no
woman in the array.
In a separate class, write a main function in which the whole
functionality of the class Person is tested.
I checked some tutorials and explanations, I didn't go straight here asking for help but after 2 hours of ripping my hair out I've been only able to come up with this:
public class Person {
String name;
int yob; //year of birth
public Person() {
Person jan = new Person("Jan", 1995); //the names are polish
Person joanna = new Person("Joanna", 1993);
Person michal = new Person("Michal", 1980);
Person beata = new Person("Beata", 1979);
Person kazimierz = new Person("Kazimierz", 1998);
Person magdalena = new Person("Magdalena", 1999);
}
public Person(String name, int yob) {
this.name = name;
this.yob = yob;
}
public Person(String name) {
this.name = name;
this.yob = 1990;
}
public static boolean isFemale(String name) {
if(name.equals("Joanna")) {
return true;
} else {
return false;
}
}
public static String getOlder(Person x?, Person y?) { // if I understand the task correctly, I should reference any two names?
if(x?.yob>y?.yob) {
return x?.name;
} else {
return y?.name;
}
//getOldest and getYoungestFemale methods go here
}
}
However, I can't wrap my head around the last three steps. My brain is literally boiling. It would really help if anyone could explain the last three bullet points (getOlder reference to any 2 people and getOldest/getYoungestFemale)
If you don't have time to explain, some example of a "method taking a reference to an array" should be enough for me to get a basic understanding.
Thanks in advance.
Usually.. you don't call it "reference to an array of references of something" You just say "array of something". Even though arrays of objects are arrays of references to objects. Just like a variable for an object is just a reference to an object.
Type heyImAReference = new ImTheObject();
So when you write
Person person = new Person();
You'll have the class Person as type, person as a reference to an instance (or object) of that class and the resulting entity of new Person() as the actual thing that is being referenced. Usually called "instance" or in your case "object".
When it comes to arrays of persons and you do
Person[] persons = new Person[5];
You create via new Person[5] an array instance that has 5 slots, in each slot can go a Person instance figuratively, actually though you have 5 references. Person[0] being the first, Person[1] being the second and so on. So that is an "array of references to objects of class Person".
And persons is a reference to that. So it is a "reference to an array of references to objects of class Person"
static function getOldest taking the reference to an array of references to objects of class Person and returning the reference to the oldest person represented in the array
means nothing more than
static Person getOldest(Person[] persons) {
...
}
I would call that a method that takes an array of Persons and returns a Person. Though technically, it's all just references that go in and come out. The Person objects don't "move"
Firstly create another class which will have main method. Within main create an array:
Person[] parr = new Person[6];
//Then fill all your person to this array:
parr[0] = new Person("name", year);
parr[1] = ....
Then pass this array handler to your methods:
Person p1 = Person.findSomething(parr);
In Person class:
public static Person findSomething(Person[] parr){
for (Person p : parr){
if (p.name.endsWith("a")) return p;
}
return null;
}
Here are some hints which should help you work out the answer yourself without me giving away the solution ;)
1)
public static String getOlder(Person x?, Person y?) {
// if I understand the task correctly, I should reference any two names?
if(x?.yob>y?.yob) {
return x?.name;
} else {
return y?.name;
}
}
This code is almost correct! Just remove the question marks! Also remember that the older person will have an earlier yob. EDIT, also you need to return the reference to the person, not their name, so return either x or y.
2) getOldest and getYoungestWoman
Person[]
is an array of references to Person objects. You should be able to read up on how to loop through the elements of an array and compare values.
3) an extra: if you declare those 6 Person objects inside the constructor, you won't be able to access them in other methods of the class. it is ok to create the Person objects there, but you must declare them outside the constructor. Declare them in the class.
For my homework, we've been tasked with creating:
Person class with variables firstName, lastName, streetAddress, zipCode and phone.
CollegeEmployee extends Person and adds ssn, salary, and deptName.
Faculty extends CollegeEmployee by adding a boolean tenure.
Last but not least, Student extends person by adding GPA and major.
Everything looks good displaying to screen, and I'm moving on to the next part of the assignment which is to create 14 records (7 students, 4 employees and 3 faculty) in an array.
3 different classes, with multiple data types, and I cannot for the life of me figure out how to populate an array with this. This is the first array I've created that's not been completely integer. The Java Tutorials didn't give me anything, and while Java: Generic Static Multidimensional Arrays has some great information, it's a little more than I can wrap my head around right now.
I'd initially thought of creating array[14][10] -- fourteen variables each for ten objects -- but I can't mix data types. That's where I got lost.
Anyone have any suggestions on how to design this array and be able to display the values from it afterward?
Any hints and suggestions would be appreciated!
Thanks.
From what I understand, no need to get fancy with multi-dimensional arrays.
1) Create an array that takes Person instances.
Person [] myPeeps = new Person[14];
2) Create a print method on Person, which subclasses override to print the relevant info.
Because your array expects Person instances, you can put instances of any subclasses of Person, because subclasses always have an is-a relationship with their superclass.
Because Person has a print method, you can call print on anything you pull out of the array. Subclasses provide their own implementations so they can print their relevant data. That way, you don't really care about which subclass any particular instance is; the correct print implementation for the instance is invoked at runtime.
You don't need a multidimensional array. You can make an array of Person objects.
Person[] people = new Person[14];
people[0] = new Student();
people[1] = new Employee();
.
.
.
You could also create a Person[] array, just as you would an int[] array. e.g.
Person[] people = new Person[14]
You can then add people to the Array like this:
people[0] = new Student();
people[1] = new CollegeEmployee();
people[2] = new Faculty();
If you want to check what type of person is in each index you will want to use instanceof. Try looking here for more help
One example of using instanceof is:
if(people[0] instanceof Student){
System.out.println("This person is a student");
}
Or try using generics.
You could create an ArrayList<Person> and can then add any type of person to this ArrayList.
e.g.
ArrayList<Person> peopleList = new ArrayList<Person>();
//People can be added like this
peopleList.add(new Student());
peopleList.add(new CollegeEmployee();)
Again you are able to use instanceof to check which type of person is in each index!
Also if you never write
Person person1 = new Person();
In your code then consider making your class abstract.
To start:
Person[] myArray = new Person[14];
This is essentially why object oriented programming is so wonderful. If you'll notice, all Faculty, CollegeEmployee, and Student are a subset of type Person. Because of this, you can have them all contained in the same dataset if it is declared as type Person.
Person[] array = new Person[14];
You can add all of your objects to that array; however, be careful. When you go to use the elements of the array Java now only knows that each has the methods that a Person does - so therefore you can only make use of firstName, lastName, streetAddress, zipCode, and phone from these elements unless you cast the objects after they are retrieved.
Since they are all of type Person, why not use a Person array?
Person [] people = new Person[14];
You can safely add all types of Person to this array, however you can only treat them as Person (without casting). To have each subclass output customized details, and add this method in Person
class Person {
void print() {
// default Person printing
}
}
and override this method in each subclass to print its member variables:
class Student extends Person {
void print() { // <-- note same method signature!
// print "I'm a Student", GPA, major
}
}
and when the array is populated:
for (Person p : people) {
p.print(); // delegates to print method associated with the underlying type
}
Check out the inheritance tutorial
The class Person is a common superclass to all the types of the objects you want to store in the array. You can create the array based on that common supertype. Then you can access methods that are defined in that tpe on all elements of the array, regardless of the actual type -- the behavior is as defined in the actual type (look up inheritance for java if this is not clear).
If you need specific behavior based on the actual type, you need to cast the array element to the concrete type (you can determine it using instanceof, for example)