Let's say you got a class x with a method copy().
This method copy() gets a class y as a param. copy(y test).
My question is, how do I make a new object out of the class that's sent as param just like this:
public void copy(y villy){
villy v = new villy();
}
You should consider that the y class is a parent one, and that I'll be passing as params its childs aswell, so what that method should do is creating a new object of the class that's sent as param!
If the parameter is a Class reference, and the class has a public constructor with no parameters:
public void copy(Class cls){
Object obj = cls.newInstance();
}
If the parameter is some object implementing the Cloneable interface, and another object of the same class is required:
public void copy(Cloneable obj1){
Object obj2 = obj1.clone();
}
EDIT 20.01.2016
So I assume that every object is a Pokemon, which has some abilities, and it has a method copy used to copy the abilities of another Pokemon. Then I would do it like this:
public class FET {
public static void main(String[] args){
Pokemon aerodactyl = new Pokemon (new Ability[]{ Ability.WALK, Ability.FLY });
Pokemon golduck = new Pokemon (new Ability[]{ Ability.WALK, Ability.SWIM });
System.out.println ("aerodactyl = " + aerodactyl);
System.out.println ("golduck = " + golduck );
System.out.println ();
golduck.copy (aerodactyl);
System.out.println ("aerodactyl = " + aerodactyl);
System.out.println ("golduck = " + golduck ); // golduck has now the same abilities as aerodactyl
System.out.println ();
aerodactyl.abilities[0] = Ability.EXPLODE; // change aerodactyl's abilities
System.out.println ("aerodactyl = " + aerodactyl);
System.out.println ("golduck = " + golduck ); // abilities of aerodactyl have changed but golduck's not
System.out.println ();
}
}
enum Ability {
WALK,
FLY,
SWIM,
TALK,
EXPLODE
}
class Pokemon {
public Ability[] abilities;
public Pokemon (Ability[] abilities) { // constructor
this.abilities = abilities;
}
public void copy (Pokemon p) { // copy abilities of another Pokemon
abilities = (Ability[]) p.abilities.clone();
}
public String toString() { // string representation of Pokemon
String str = "Pokemon";
if (abilities != null) {
for(int i = 0; i < abilities.length; i++) {
str += (i==0) ? ": " : ", ";
str += abilities[i];
}
}
return str;
}
}
Related
I was wondering, whether it would be possible to assign a unique ID for every new class (not instance!).
Example of what I mean:
public class ChildObjectOne extends SuperClass {}
public class ChildObjectTwo extends SuperClass {}
public SuperClass {
private final int ID;
public SuperClass() {
this.ID = newID();
}
}
final ChildObjectOne childObjectOne = new ChildObjectOne();
final ChildObjectTwo childObjectTwo = new ChildObjectTwo();
System.out.println(childObjectOne.getID()); //prints 1
System.out.println(childObjectOne.getID()); //prints 2
childObjectOne = new ChildObjectOne();
childObjectTwo = new ChildObjectTwo();
System.out.println(childObjectOne.getID()); //prints 3
System.out.println(childObjectOne.getID()); //prints 4
What I want it to do instead is print 1 and 2 again. It should generate a new ID for every new class, but if I create a new instance of that class, I want the ID to stay the same.
I tried to achieve this using generics:
public SuperClass<T> {
private static int ID;
public SuperClass() {
this.ID = newID();
}
}
public class ChildObjectOne extends SuperClass<ChildObjectOne> {}
public class ChildObjectTwo extends SuperClass<ChildObjectTwo> {}
I was hoping, it would count passing a different T as a new class, but that didn't work. Instead the ID is the last one that was set.
How can I achieve this kind of ID system?
To expand upon my comment, the class name will give you an unique String ID. If you want that ID to be a number you could do something like this:
class IdGenerator{
private static int counter = 0;
private static HashMap<String,Integer> classIdMap = new HashMap<>();
public static synchronized int getId(Class clazz){
if (classIdMap.containsKey(clazz.getName())) {
return classIdMap.get(clazz.getName());
} else {
classIdMap.put(clazz.getName(), ++counter);
return counter;
}
}
}
And then from your class you would do:
IdGenerator.getId(this.getClass());
The generated IDs might not be the same every time you run your app, depending on how it is structured.
For example:
Scanner in = new Scanner(System.in);
if (in.nextInt() < 100) {
System.out.println("a = " + new Aclass().id); // a = 1
System.out.println("b = " + new Bclass().id); // b = 2
} else {
System.out.println("b = " + new Bclass().id); // b = 1
System.out.println("a = " + new Aclass().id); // a = 2
}
Class::getName
Each class in Java already carries a unique identifier: the fully-qualified name of the class. No need for you to add an identifier.
Access the fully-qualified name by calling Class::getName.
For a class:
String.class.getName()
"java.lang.String"
For an object (an instance), call Object::getClass, and then Class::getName.
customer.getClass().getName()
com.example.invoicing.Customer
I am learning java. I would like to have a enum as a parameter in my constructor. But I am getting an error
(I have my enum in a separate class that is public and named AvailabilityState {AVAILABLE,ORDERED,REMOVED }
public class Facultymember extends User {
private int MAX_GENERALBOOKS = 5;
private int MAX_AUDIOBOOKS = 2;
private AvailabilityState aStatus;
public Facultymember(int genbook, int audbook,AvailabilityState aStatus ){
this.MAX_GENERALBOOKS=genbook;
this.MAX_AUDIOBOOKS=audbook;
this.aStatus = aStatus;
}
#Override
public String toString() {
return "Facultymember {" + "MAX_GENERALBOOKS=" + MAX_GENERALBOOKS+ ", MAX_AUDIOBOOKS =" + MAX_AUDIOBOOKS + "AvailabilityState," + aStatus + '}';
}
}**
If you require a parameter of type AvailabilityState, you should provide it, like so:
User availableFaculty = new Facultymember(5,2, AvailabilityState.AVAILABLE);
User orderedFaculty = new Facultymember(5,2, AvailabilityState.ORDERED);
User removedFaculty = new Facultymember(5,2, AvailabilityState.REMOVED);
Alternatively, define another constructor with default availability state:
public Facultymember(int genbook, int audbook) {
// assuming availability by default
this(genbook, audbook, AvailabilityState.AVAILABLE);
}
This question already has answers here:
Why does my ArrayList contain N copies of the last item added to the list?
(5 answers)
Closed 6 years ago.
This if my first question on stackoverflow. I can usually find answers myself but I'm having trouble with this one. I've got 2 objects, "Book", and "Periodical". These are subclasses to a class "Publication". Now, I'm trying to add 3 instances of "Book" and 3 instances of "Periodical" to an ArrayList. I'm having trouble figuring out how to do this.
With this current code, I get an error "no suitable method found for add(Book,Book,Book,Periodical,Periodical,Periodical).
Here is the current code:
import java.util.ArrayList;
import java.util.Date;
public class DriverProgram {
public static void main(String[] args) {
// Instantiate 3 instances of each object.
Book book1 = new Book(1234, 1, "James", 100, "Hello", "Berkwood Inc.", new java.util.Date(), "History");
Book book2 = new Book(2345, 2, "Ralph", 200, "Goodbye", "Shackles Co.", new java.util.Date(), "English");
Book book3 = new Book(3456, 3, "Julia", 300, "Hello Again", "Trustin Inc.", new java.util.Date(), "History");
Periodical periodical1 = new Periodical("Daily", "Dylan", "History 101", "History Inc.", new java.util.Date(), "History");
Periodical periodical2 = new Periodical("Weekly", "Jannette", "Mathematics 101", "Mathematics Inc.", new java.util.Date(), "Mathematics");
Periodical periodical3 = new Periodical("Monthly", "Patricia", "Science 101", "Science Inc.", new java.util.Date(), "Science");
// Create an array list of the Publication class type, and add the objects to it.
ArrayList <Publication> publications = new ArrayList<Publication>();
publications.add(book1, book2, book3, periodical1, periodical2, periodical3);
// Pass the array list to a method to loop through it and display the toString methods.
displayObjects(publications);
} // End of main
static void displayObjects (ArrayList<Publication> publications) {
// Loop through array list and display the objects using the toString methods.
for (Publication p : publications) {
System.out.print(p.toString());
} // End of for each loop
} // End of displayObjects
} // End of DriverProgram class
I've also tried changing:
publications.add(book1, book2, book3, periodical1, periodical2, periodical3);
To this:
publications.add(book1);
publications.add(book2);
publications.add(book3);
publications.add(periodical1);
publications.add(periodical2);
publications.add(periodical3);
Which rids my program of the compiler error, but then it just prints the "periodical3" object, 6 times. I'm not sure what I'm doing wrong. Any suggestions? Thank you in advance! :)
EDIT:
Here is my Book class:
public class Book extends Publication{
private static int isbn = 0;
private static int libraryOfCongressNbr = 0;
private static String author = "";
private static int nbrOfPages = 0;
// Constructor for Book class with parameters for each attribute.
public Book(int newISBN, int newLibraryOfCongressNbr, String newAuthor, int newNbrOfPages, String newTitle, String newPublisher, java.util.Date newPublicationDate, String newSubject) {
super(newTitle, newPublisher, newPublicationDate, newSubject);
isbn = newISBN;
libraryOfCongressNbr = newLibraryOfCongressNbr;
author = newAuthor;
nbrOfPages = newNbrOfPages;
}
/////////////////////////////////////////////////////// Getters ///////////////////////////////////////////////////////
int getISBN() {
return isbn;
}
int getLibraryOfCongressNbr() {
return libraryOfCongressNbr;
}
String getAuthor() {
return author;
}
int getNbrOfPages() {
return nbrOfPages;
}
/////////////////////////////////////////////////////// Setters ///////////////////////////////////////////////////////
void setISBN(int newISBN) {
isbn = newISBN;
}
void setLibraryOfCongressNbr(int newLibraryOfCongressNbr) {
libraryOfCongressNbr = newLibraryOfCongressNbr;
}
void setAuthor(String newAuthor) {
author = newAuthor;
}
void setNbrOfPages(int newNbrOfPages) {
nbrOfPages = newNbrOfPages;
}
//toString method for Book class
public String toString () {
StringBuilder result = new StringBuilder();
result.append("\nISBN: " + isbn + "\n");
result.append("\nPublisher: " + libraryOfCongressNbr + "\n");
result.append("\nAuthor: " + author + "\n");
result.append("\nNumber of Pages: " + nbrOfPages + "\n");
result.append("--------------------------------------------------------- ");
return super.toString() + result.toString();
} // End of toString
} // End of Book class
My Periodical class is identical, but here is my Publication class:
import java.util.Date;
public abstract class Publication {
// Data fields.
private static String title = "";
private static String publisher = "";
private static java.util.Date publicationDate;
private static String subject = "";
// Constructor for Publication class with parameters for each attribute.
public Publication(String newTitle, String newPublisher, java.util.Date newPublicationDate, String newSubject){
title = newTitle;
publisher = newPublisher;
publicationDate = newPublicationDate;
subject = newSubject;
}
/////////////////////////////////////////////////////// Getters ///////////////////////////////////////////////////////
String getTitle() {
return title;
}
String getPublisher() {
return publisher;
}
java.util.Date getPublicationDate() {
return publicationDate;
}
String getSubject() {
return subject;
}
/////////////////////////////////////////////////////// Setters ///////////////////////////////////////////////////////
void setTitle(String newTitle) {
title = newTitle;
}
void setPublisher(String newPublisher) {
publisher = newPublisher;
}
void setPublicationDate(java.util.Date newPublicationDate) {
publicationDate = newPublicationDate;
}
void setSubject(String newSubject) {
subject = newSubject;
}
//toString method for Publication class
public String toString () {
StringBuilder result = new StringBuilder();
result.append("\nTitle: " + title + "\n");
result.append("\nPublisher: " + publisher + "\n");
result.append("\nPublication Date: " + publicationDate + "\n");
result.append("\nSubject: " + subject + "\n");
return result.toString();
} // End of toString
} // End of Publication class
Let me know if you need anything else!
EDIT x2: Sorry, I realize my post is getting quite long.
So I've gotten rid of all "static" keywords from my class variables, or "data fields" as I've called them in my code. I then changed my code back to this code:
ArrayList <Publication> publications = new ArrayList<Publication>();
publications.add(book1);
publications.add(book2);
publications.add(book3);
publications.add(periodical1);
publications.add(periodical2);
publications.add(periodical3);
And it works! It executes as it should! I just one question though, since this code doesn't seem to work:
publications.add(book1, book2, book3, periodical1, periodical2, periodical3);
Is there a shorter way to add all of the objects to the ArrayList with out doing it one by one?
If I understand the problem correctly, you have 6 Publication objects, and you are only seeing the values of the most recently created one.
That would likely be caused because you have static class variables instead of instance variables.
For example
class A {
static int x; // class variable
int y; // instance variable
public A(int val) {
x = val; // All 'A' classes now have x = val;
y = val; // Only 'this' class has y = val;
}
}
If I were to run this
A a1 = new A(4);
A a2 = new A(5);
System.out.println(a1.x);
Then I would see it print 5 and not 4, which describes the scenario you are seeing because you have assigned all variables in the Publication class to those that you use during the last call of new Periodical.
The solution is to not use static variables if you want to have multiple instances of a class with their own values.
I have the following code to retrieve information from a text box to another within the same class
btnAddItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String tabno = textArea_TableNo.getText();
String name = textArea_Name.getText();
String size = textArea_size.getText();
String quan = textArea_quantity.getText();
String price = textArea_price.getText();
textArea.append(tabno + ", " + name + ", " + size + ", " + quan + ", " + price + "\n");
But I am not sure how to do this exactly same operation between two class. I probably have to "extend" my class but I've already extended the class to my database class. Im just not sure how else I can do this. Any suggestions to get my head around this would be appreciated..
Well, you can have a public method to retrieve the text, and use this on another class. For example:
class Class1 {
private JTextArea textOne;
//... declare other fields, build GUI, etc
public String getTextOneText() {
return textOne.getText();
}
}
class Class2 {
private JTextArea textTwo;
private Class1 class1;
public Class2( Class1 class1 ) {
this.class1 = class1; //store reference to class1.
}
//use the getData method to append text from the Class1.
void getData() {
textTwo.append( class1.getTextOneText() )
}
}
In this example, storing the reference to the instance of Class1 in Class2 and using the method getData should do what you want.
Another way is use the Observer Design Pattern to communicate between classes.
I'm trying to find a way to list which objects a run-time object is referring to. I know there is a way to enquire the jvm using oql but what I'd like to do is to query it from inside a program. Is there any API I could use?
You can do it via Reflection (java.lang.reflect).
How is described in this article. Basically, given this class that has private members:
public class Secret {
private String secretCode = "It's a secret";
private String getSecretCode(){
return secretCode;
}
}
With Reflection, you can access all of its members (including the private ones), including their values. And so you look at all of its data members to see what they refer to (and of course, you can repeat the process if they also refer to other objects). Here's how to access their members (this code shows methods as well, which you probably won't need if you're just interested in data, but I didn't see any good reason to pull that part out):
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Hacker {
private static final Object[] EMPTY = {};
public void reflect(Object instance)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class secretClass = instance.getClass();
// Print all the method names & execution result
Method methods[] = secretClass.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
// Print all the field names & values
Field fields[] = secretClass.getDeclaredFields();
System.out.println("Access all the fields");
for (int i = 0; i < fields.length; i++){
System.out.println("Field Name: " + fields[i].getName());
fields[i].setAccessible(true);
System.out.println(fields[i].get(instance) + "\n");
}
}
public static void main(String[] args){
Hacker newHacker = new Hacker();
try {
newHacker.reflect(new Secret());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
I've fixed a bug in their original code and made a small change to make it more clear that Hacker is not in any way tied to Secret (other than in main).
Update: Re your question below about the fields from base classes, here's an updated Hacker that does that (I've assumed you don't want to try to enumerate the fields on Object, so I've stopped there):
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Hacker {
private static final Object[] EMPTY = {};
public void reflect(Object instance)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class cls = instance.getClass();
while (cls != null && cls != Object.class) {
System.out.println("From class: " + cls.getName());
// Print all the method names & execution result
Method methods[] = cls.getDeclaredMethods();
System.out.println("Access all the methods");
for (int i = 0; i < methods.length; i++) {
System.out.println("Method Name: " + methods[i].getName());
System.out.println("Return type: " + methods[i].getReturnType());
methods[i].setAccessible(true);
System.out.println(methods[i].invoke(instance, EMPTY) + "\n");
}
// Print all the field names & values
Field fields[] = cls.getDeclaredFields();
System.out.println("Access all the fields");
for (int i = 0; i < fields.length; i++){
System.out.println("Field Name: " + fields[i].getName());
fields[i].setAccessible(true);
System.out.println(fields[i].get(instance) + "\n");
}
// Go to the base class
cls = cls.getSuperclass();
}
}
public static void main(String[] args){
Hacker newHacker = new Hacker();
try {
newHacker.reflect(new Secret());
}
catch (Exception e) {
e.printStackTrace();
}
}
}
When combined with
public class BaseSecret {
private String baseSecretCode = "It's a base secret";
}
and
public class Secret extends BaseSecret {
private String secretCode = "It's a secret";
private String getSecretCode(){
return secretCode;
}
}
you get:
$ java Hacker
From class: Secret
Access all the methods
Method Name: getSecretCode
Return type: class java.lang.String
It's a secret
Access all the fields
Field Name: secretCode
It's a secret
From class: BaseSecret
Access all the methods
Access all the fields
Field Name: baseSecretCode
It's a base secret
You can use getClass() method of Object class to get the runtime class of an object.