Dynamically naming an instance of a class? - java

Just a really quick question about something small. The following is part of a programming assignment for my programming 2 class. It focuses on inheritance and multiple classes. I've answered the question but want to consolidate the classes into a main function and actually build something rather than just submitting the bare minimum.
My question is the section of code below. The user runs the program, is presented with a dialog asking him as to what he's like to add (a CD or a Movie, they're both separate classes).
What I would like though, is for the user to actually name the specific instance of the class while the program is running. So, the user will click Movie for example, be prompt to enter a name and then next line to use the constructor in the movie class to create a new instance class with the name the user entered? Is this possible? I tried using a simple string x = JOptionpane and then naming the class x also, but it didn't work. I'm thinking there might be some method that will refer to the string? like contents.x maybe?
thanks in advance!
import javax.swing.JOptionPane;
public class Main
{
public static void main (String args [])
{
Object[] options = {"Movie",
"CD",
"Cancel"};
int n = JOptionPane.showOptionDialog(null, "Would you like to add an item?","Product",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[2]);
switch(n)
{
case 0:
String moviet = JOptionPane.showInputDialog("Title:");
int movieID = Integer.parseInt(JOptionPane.showInputDialog("ID:"));
Movie moviett = new Movie(moviet, movieID);
}
}
}

If it's not too far beyond your class' content, you could use a Map<String, Media>1 to store instances identified by a runtime-specified string.
Map<String, Media> instances = new HashMap<>();
// snip...
String moviet = JOptionPane.showInputDialog("Title:");
int movieID = Integer.parseInt(JOptionPane.showInputDialog("ID:"));
Movie moviett = new Movie(moviet, movieID);
instances.put("some user-provided string", moviett);
1Assuming that Movie and CD both extend/implement Media.

Java doesn't work this way, and in fact variable names are much less important than you think and almost don't exist in compiled code. Instead how about using Strings to set a field of the Movie class, perhaps a String field called "name". If you want to retrieve a class instance based on a String, consider using a Map such as a HashMap.

Related

How do I add a User Input of type String to an ArrayList in Java?

I am attempting to make a course registration system and one of my classes (Course) is centered around course attributes (ie. Course number, course name, instructors, students). I am making an ArrayList so that the Administrator (one of the user types) may add as many instructors to the course as he/she would like- I have created a Scanner and a String variable and everything, but when I write the .add command, Eclipse highlights ".add" and says "the method .add() is undefined for the type of scanner". Now, I can understand this, but I have no idea how to fix it and I've tried so many ideas.
Here is the method:`
public static String Instructor(){
String courseInstructors;
System.out.println("Please add name(s) of course instructors.");
ArrayList<String> Instructors= new ArrayList<String>();
Scanner courseInst = new Scanner(System.in);
courseInstructors = courseInst.next();
//courseInst.add(courseInstructors);
for(String courseInstructors1 : Instructors) {
courseInstructors1 = courseInstructors;
courseInst.add(courseInstructors1);
}
return;
}`
Please adhere to Java naming conventions ad use lower case for variable names - instructors instead of Instructors.
Also, you want to add to your arraylist, so call add() on
instructors.add(courseInstructors1)
You may also want to consider choosing better variable naming than courseInstructors1, for instance just courseInstructor, since you are referring to on instructor of all instructors.
Also in your for loop you are doing the following
for(String courseInstructors1 : Instructors) {
courseInstructors1 = courseInstructors;
courseInst.add(courseInstructors1);
}
This can be simplified to
for(String courseInstructors1 : Instructors) {
courseInst.add(courseInstructors);
}
And if you look at the simplification you will see that iterating through Instructors make no sense here, since you are not using the contents of courseInstructors1.
I'm trying to understand what your loop is for.
if you are trying to get multiple instructor names from one input then you need something like this.
//get input
//"John Peggy Adam blah blah"
courseInstructors = courseInst.next();
//split the string by white space
String[] instArr = courseInstructors.split(" ");
//will give array of John, Peggy, Adam, blah, blah
Then do your foreach loop to add them to the list.
for(String inst: instArr){
instructors.add(inst);
}
Otherwise I would suggest doing something like this so you don't have to worry about splitting names and such.
courseInstructor = courseInst.nextLine();
while(!courseInstructor.equals("done"){
//add name to list of instructors.
instructors.add(courseInstructor);
//get next name.
courseInstructor = courseInt.nextLin();
//if the user types done, it will break the loop.
//otherwise come back around and add it and get next input.
}

How to load data into java program without bloating main method

I'm looking for some object oriented design help basically.
At the start of my program I need to load a whole bunch of data into the program(not from a database or anywhere; in this case I'm just loading it into the program) by building objects and assigning variables. However this takes up a lot of room and I feel like I'm just clogging up the main method and making it unreadable.
I'm wondering what's the right way to approach this is, as far as OOP goes.
I tried to make a class SubjectBuilder, and create everything in the constructor or variable space, and then create a new object in the main method. But it seems that alldata is out of the scope of the main method so when I need to manipulate it later I can't.
Student jack = new Student("Jack Smith"); // Creating all the Student objects
Student jim = new Student("Jim Lucas");
Student beck = new Student("Beck Barber");
Student ann = new Student("Ann Walker");
Student lucy = new Student("Lucy Boxer");
Subject maths = new Subject("Maths"); // Creating all the Subject objects
Subject business = new Subject("Business");
Subject java = new Subject("Java");
Subject design = new Subject("Design");
Subject project = new Subject("Project");
business.addStudent(jack, 70);
business.addStudent(jim, 65);
business.addStudent(beck, 70);
business.addStudent(ann, 83);
business.addStudent(lucy, 78);
^^ That's a snippet data I need to load. I have a bunch of marks for each subject.
At this stage I only have the Application class, Subject class (HashMap of student and Integer mark), and Student.
All I need to do is create this program that displays individual data for students or subjects and allows changes to particular marks etc. I'm confident I could complete the whole project in the main method but I feel like that's not very object oriented. I just don't know how to do it otherwise.
Firstly, how about creating a method to do this so it is not in your main
e.g.
Class MyClass {
public void main (String args[]) {
myClass mc = new MyClass();
mc.loaddata ();
}
private void loadData () {
}
Now in your loadData method you could load this data from a CSV file maybe? See http://opencsv.sourceforge.net/
A simple suggestion for: create a StudentFactory to encapsulate students instantiation, the facory method might looks like: public List createAllStudents();
And the same to Subject class.
If you are only going to access the students from the business class you could do the following
business.addStudent(new Student("Jack Smith"), 70);
business.addStudent(new Student("Jim Lucas"), 65);
business.addStudent(new Student("Beck Barber"), 70);
business.addStudent(new Student("Ann Walker"), 83);
business.addStudent(new Student("Lucy Boxer"), 78);
Keep your data in arrays or some other data structure like
String names = {"Jack Smith","John","Asley"};
int grades = {70,65,85}; //you can generate local or global array , its up to you
int main()
{
for(int i=0;i<names.length;i++)
business.load(names[i],grades[i]);
}
//Do your work in load method
You should use a map to hold your students, and use Long or String or any other immutable class as your key. I recommend using a Map because it's O(1) to access data from this kind of collection, against O(n) if you use, for instance, an ArrayList<Students>.
private Map<Long, Student> students = new HashMap<>();
Then you should move your loading data to a method such as:
private void loadStudents(){
student.put(1L , new Student("Jack Smith"));
student.put(2L , new Student("Joe Doe"));
student.put(3L , new Student("Jane Doe"));
}
For your Subject you could use again some map:
private void loadSubjects(){
subjects.put("MATH" , new Subject("Mathematics"));
subjects.put("JAVA" , new Subject("Java"));
subjects.put("DESING_PATTERNS" , new Subject("DesingPatterns"));
//for instance you could have more advanced subjects such as:
subjects.put("C++" , new Subject("C++" , "lecture" , "class 101" , "prof. T. Richards"));
}
Since by calling an object's constructor means that that object is ready for use, you should call your loadStudent() (and possibly loadSubjects() method, or any methods you use to load your data into the application) into this constructor.
public BusinessLogic(){
loadStudents();
loadSubjects();
//and so on
}
This is the prefered way against having to call load data methods on your newly created object, and always remembering you have to call these methods before using your object:
BusinessLogic business = new BusinessLogic();
business.calculateFinalGrades(); // NOT GOOD BECAUSE YOU HAVE FORGOTTEN TO CALL loadStudents();
So, you'll end up having something like:
public static void main(String[] args){
buildUI();//build your command line interface / graphical user interface
BusinessLogic businessLogic = new BusinessLogic();//you can probably now make this object a Singleton in order to prevent having multiple instances
...
}
You are right, building the whole application in the main is not the way to do it. In my opinion you should build a class that provides data let's say DataProvider that has methods for providing given data. As there are multiple ways of storing data, you can make this an interface/ abstract class depending on the common code. As your project can evolve and later maybe you want to extract data from DB or XML or something else. Like this it will be loose coupled and easy to replace. It might look like this:
interface DataProvider<T> {
Collection<T> loadData();
//...other useful methods
}
class DummyStudentDataProvider implements DataProvide<Student> {
Collection<Student> loadData() {
///...your logic
}
}
I used generics as the same logic could be used for different classes that you might need. Hope this helps you.

Fill an Array with different data types

i need to fill an Array with different data types
InvoiceItem[] invoiceItems;
int test = 3;
int i = 0;
This needs to be in the Array:
InvoiceItem invoiceItem = new InvoiceItem();
invoiceItem.setItemType("TestItem");
invoiceItem.setArticleNo("TestItemID");
invoiceItem.setDescription("TestDescription");
invoiceItem.setQty(1);
invoiceItem.setPrice(new BigDecimal(20.00));
invoiceItem.setVat(new BigDecimal(5.0));
There is the possibility that there is more than one InvoiceItem (test=3), so it needs to be in a loop.
It has to be an Array, i need to pass it to another class which only accepts an Arrays.
How can i achieve this?
Edit: I will try to make my question more clear:
I need to know how to put these
invoiceItem.setItemType("TestItem");
invoiceItem.setArticleNo("TestItemID");
invoiceItem.setDescription("TestDescription");
invoiceItem.setQty(1);
invoiceItem.setPrice(new BigDecimal(20.00));
invoiceItem.setVat(new BigDecimal(5.0));
in an Array:
int countofInvoiceItem = 3; // there are 3 InvoiceItem
InvoiceItem[] invoiceItems = new InvoiceItem[countofInvoiceItem];
Where there can be more than one InvoiceItem.
Method looks like this:
public final ResponseCreateInvoice CreateInvoice
(Invoice Invoice, InvoiceItem[] InvoiceItems, Address DeliveryAddress, Address InvoiceAddress, String UserID, String Password)
(This is given and i can not change)
and returns
ResponseCreateInvoice inv = wsClient.createInvoice(invoice, invoiceItems, deliveryAddress, invoiceAddress, userID, password);
i am sort of new to Java (or arrays), so this may be an easy question, but i don't really get it. Also does it matter that there are Strings and Int, BigDecimal etc mixed together in an Array?
You just need to declare your array as an array of type T where T is a superclass of all the classes of the objects you want to fill it with. In the worst case, it would be Object but it's bad design 9 times out of 10.
I would recommend you to make a class that holds everything you need as follows:
public class YourClass{
int id;
double value;
String description;
//and so on
//create getters and setters
}
And you can use this class to pass array of objects to another class.
Put your objects of the class in the Array
For example
YourClass[] objects = new YourClass[SIZE];//define number of objects you need
And you can pass each and every objects separately or as a whole to another class.
And in your receiving class, you can have a constructor as:
public YourRecievingClass(YourClass[] object){
//and recieve here as you need; ask further if you need help here too
}
I think this is the best way to adopt though your question is not 100% clear
Based on your edit, your original question is off base. You do not want to create an array of different types but instead only want to create an array of one type and one type only, that being an array of InvoiceItems. You are confusing object properties with array items, and they are not one and the same. This code here:
invoiceItem.setItemType("TestItem");
invoiceItem.setArticleNo("TestItemID");
invoiceItem.setDescription("TestDescription");
invoiceItem.setQty(1);
invoiceItem.setPrice(new BigDecimal(20.00));
invoiceItem.setVat(new BigDecimal(5.0));
is where you are changing the properties of a single InvoiceItem.
It seems that your InvoiceItem class has String fields for item type, for article number, for description, an int field for quantity, a BigDecimal field for price and a BigDecimal field for VAT. And so your array would look simply like:
InvoiceItem[] invoiceItems = new InvoiceItem[ITEM_COUNT]; // where ITEM_COUNT is 3
You could use a for loop to then create your items:
for (int i = 0; i < invoiceItems.length; i++) {
invoiceItems[i] = new InvoiceItem();
}
And you could perhaps use the same for loop to fill in the properties of each InvoiceItem in the array:
for (int i = 0; i < invoiceItems.length; i++) {
invoiceItems[i] = new InvoiceItem();
invoiceItems[i].setItemType(???);
invoiceItems[i].setArticleNo(???);
invoiceItems[i].setDescription(???);
invoiceItems[i].setQty(???);
invoiceItems[i].setPrice(???);
invoiceItems[i].setVat(???);
}
But the unanswered question is, ... where do you get the data for each property of each InvoiceItem in the array? Is this information contained in a file? Is it inputted by the user? That is something you still need to tell us.
With which types of data? In general, you could use:
Object[] myArray;
All classes are subclasses of Object.

Calling an Instance method when user inputs the instance name as a String

In a small project I am working on I've gotten stuck. The user enters a command that may be "xp Speed", my command handler class finds that it wants to the XP value of the Speed Instance. In this case it needs to return the value of Skill.Speed.currentXP back to the user.
Small Part of the program:
//Example Instance initialization there is over 40 of these
Skill Speed = (new SkillSpeed(Skills.SKILL_SPEED,Skills.SKILL_SPEED_MODIFIER));
//Constructor for skill class
public Skill(String skillName, double modifier) {
this.name = skillName;
this.minLevel = Skills.MIN_SKILL_LEVEL;
this.Modifier = 1f;
this.currentLevel = (int)calculateLevel();
this.currentXP = 1;
this.leaderboard = getCurrentLeaderboard();
this.ID = getNextID();
}
Now, theres one way i could do this. by having a switch statement with case value being the string entered. However I'm sure having 40+ cases in one switch statement must be avoidable. The other theory I have had is creating a array of all current instances then iterating through that list, finding if the user inputted string is equal to the name of that instance, then returning the instance itself. This is what I came up with:
//method inside another classs that attempts to return the appropriate skill Instance
public Skill getSkillFromName(String Name) {
for(int i = 0; i < Skill.SkillArray.length; i++) {
final String SkillName = Skill.SkillArray[i].getName();
if(SkillName.equalsIgnoreCase(Name)) {
return Skill.SkillArray[i];
}
}
return null;
}
So here's what I need help with:
Creating a array of all initialized instances
Creating the method that will return Skill."InsertRandomInstanceDependingOnUserInputHere".currentXP
Fixing any problems you see in the getSkillFromName() method
Or perhaps I have overlooked a far easier way of doing this, and you can help me with that.
Thanks for the help,
BigDaveNz
If the names of the skills excatly match method names you might find the aswer at "How do I invoke a Java method when given the method name as a string?".
For finding instances by name you can still use Map's.
You can use a Map for this. E.g.:
Map<String, Skill> skills = new HashMap<String, Skill>();
To insert the values you put the values into the Map:
skills.put(skill.getName(), skill);
To retrieve your skill you can get the skill by name:
Skill skill = skills.get(name);

how to use same string in two java files

Sorry for my bad English and for maybe stupid question but I'm new in Java.
I need use same string in 2 java files for example:
In first java file I've got code for sending emails, I've got string set to default email:
public String mail = new String ("lala#gmail.com");
and I use this string in code for send email:
email.addTo(mail);
In second java file something like set up where can user set new email address I want to have same string, connected with string in first java file. When user put new email String mail will be change to new email address and in email.addTo(mail); will be use this new address
How can I do this?
use Shared Preferences, you can store it as key-value Pair. value being your email and key can be any unique string which you want to identify it with.
I'm a bit confused with the question, but I'll take a stab at it. Basically, you would like to have one String in a given file be used in multiple locations. This is easily done using class-level variables and making them publicly accessible.
For example, in the file:
EmailObject.java
public class EmailObject {
public static final String mail = "lala#gmail.com";
// The rest of your code
}
Another file can access this like so:
OtherObject.java
public void sendEmail() {
EmailMessage email = new EmailMessage();
email.addTo(EmailObject.mail);
}
Note the static and final modifiers on the original. This ensures that you do not need an actual instance of EmailObject to access the string and it also ensures that the string is never modified accidentally by some other object.
There are, of course, other ways to do this, but this one matches your code the most. This is also a very "Java" solution. Android has other ways to share data (as indicated by the other answer).
The simplest way that I would not recommend is to have a public static field:
class A {
public static String commonString;
}
class B {
public void methodThatUsesString () {
// Do stuff with the string
Log.d("I have the string", A.commonString);
}
}
If you have two Activities, and one starts another, you can send data through Intents.
The forementioned SharedPreferences way is a good solution too, if the email address is a persistent thing, a preference if you will, and not just data reqired for an operation.
You can keep a reference of one instance of a class in the otherone, and access it's fields through it:
class A {
public String commonString;
}
class B {
private final A instaceOfA;
public B (A instanceOfA) {
this.instanceOfA = instanceOfA;
}
public void methodThatUsesString () {
// Do stuff with the string
Log.d("I have the string", instanceOfA.commonString);
}
}
Or even use a getter or setter if performance is not an issue.
Many answers depending on how the string will be used.
If it's a constant string, one that will never change, never use final static String
public final static String AUTHOR_MAIL = "lala#gmail.com";
Then you can use it in a static way wherever you want.
email.addTo(MyClass.AUTHOR_MAIL);
If this String will be used in different Activities you can not access it directly (you can not tell if the other Activity is still alive). You have to use Persistence Mechanisms such as SharedPreferences or directly send needed data in your Intent.
If it's in a helper class inside your Activity, you can just use mObject.mail to get it.

Categories

Resources