Creating multiple objects within a class - java

I am trying to create a class. Let's call it Questionnaire. In Questionnaire, I want to instantiate a number of classes called Question. The constructor for Questionnaire accepts a string array of words, and for each word, there should be a Question class to accept it as an argument for its constructor. In other words, for every string that is passed as an argument, I want to create a Question.
I need to be able to put Questionnaire within a bigger class and still call the methods of the Question classes. The size of the array passed to Questionnaire varies as well. I don't know how I can put multiple classes within another class when I don't know how many classes there will be, and how to reference them from an outer class. If the array was a fixed length I'd just create Questions as question1, question2, question3... but since this is not the case I am not sure anymore. I do know there is a maximum number of Question classes I want to create though.
edit: I'm using J2ME CDLC 1.1 MIDP 2.0 for this (it's part of a mobile phone app) so my solutions are constrained by what it offers.

You don't want to have a separate variable per question - use a List<Question> to have one variable which refers to a collection of questions:
public class Questionnaire
{
private final List<Question> questions;
public Questionnaire(String[] words)
{
questions = new ArrayList<Question>();
for (String word : words)
{
questions.add(new Question(word));
}
}
// Use questions here
}
EDIT: If you're in an environment without generics, you could use the non-generic form, like this:
private final List questions;
public Questionnaire(String[] words)
{
questions = new ArrayList();
for (String word : words)
{
questions.add(new Question(word));
}
}
or like this if you don't have List/ArrayList:
private final Vector questions;
public Questionnaire(String[] words)
{
questions = new Vector();
for (String word : words)
{
questions.add(new Question(word));
}
}
In either case you'll need to cast on every access. Alternatively, you could use an array:
private final Question[] questions;
public Questionnaire(String[] words)
{
questions = new Question[words.length];
for (int i = 0; i < words.length; i++)
{
questions[i] = new Question(word);
}
}

As J2ME API lacks the Collections API, your best bet is to grab a Vector.
Vector questions = new Vector();
for (int i = 0; i < words.length; i++) {
questions.addElement(new Question(words[i]));
}

You probably want to go with a Set of questions rather than List. Try :
private final Set<Question> questions;
This will prevent duplicate questions. Everything else will be the same as JonSkeet's answer.

Why don't you use a List on the questionaire and for each question you add you add one to the List, for example.
public class Questionnaire
{
public List<Question> myQuestions {get; private set;}
public Questionnaire(string[] questions)
{
myQuestions = new List<Questions>();
foreach(string q in questions)
{
myQuestions.Add(new Question {questionText = g});
}
}
}
public class Question
{
public string questionText {get; set;}
}
Then you will be able to check the questions from outside... this is what you want?
Hope this helps
EDIT: ohh is Java, but you got the idea right?

import java.util.*;
public class Questionnaire implements Iterable<Question> {
private final List<Question> questions;
public Questionnaire(String ...words) {
questions = new ArrayList<Question>(words.length);
for(String word : words) {
questions.add(new Question(word));
}
}
// allows you to use a Questionnaire object in a for-each loop
public Iterator<Question> iterator() { return questions.iterator(); }
#Override
public String toString() { return questions.toString(); }
}
You could add many more goodies to your class to make it more useful. An example of using the class above follows:
public class QuestionnaireTest {
public static void main(String[] words) {
Questionnaire questionnaire = new Questionnaire(words);
for(Question q : questionnaire) {
System.out.println("You asked: " + q);
}
}
}
You could also use it as follows:
public class QuestionnaireTest3 {
public static void main(String[] words) {
// because I declared the constructor to accept "String ...words", I can specify as many questions as I want using simple syntax
Questionnaire questionnaire = new Questionnaire("How deep the ocean?", "How high the moon?");
for(Question q : questionnaire) {
System.out.println("I asked: " + q);
}
}
}
Even though I did so in my first example above, you should really accept an array of String objects as questions. Here's a better design:
public class Questionnaire implements Iterable<Question> {
private List<Question> questions = new ArrayList<Question>();
public void add(Question q) {
if(q == null) throw new IllegalArgumentException("can't add null question!");
questions.add(q);
}
public Question get(int index) {
if(index < 0 || index >= questions.size()) throw new IndexOutOfBoundsException("invalid question index: " + index);
return questions.get(index);
}
// allows you to use a Questionnaire object in a for-each loop
public Iterator<Question> iterator() {
return Collections.unmodifiableList(questions).iterator();
}
#Override
public String toString() { return questions.toString(); }
}
public abstract class Question {
public String getText();
public String getAnswer();
public String getOptions();
// ...
}
public class YesNoQuestion extends Question {
private final String text;
private final String answer;
public YesNoQuestion(String text, boolean answer) {
if(!(text.startsWith("Is"))) throw new IllegalArgumentException("Must start with is: " + text);
this.text = text;
this.answer = answer ? "Yes" : "No"; // if answer == true, the "Yes",...
}
#Override
public String getText() { return text; }
public String getAnswer() { return answer; }
public String getOptions() { return "Yes or No ?"; }
}
And now you can use it as follows:
public class QuestionnaireTest4 {
public static void main(String[] words) {
Questionnaire test = new Questionnaire();
test.add(new YesNoQuestion("Is dogs animals?", false));
test.add(new YesNoQuestion("Is me has cheezburgers?", true));
for(Question q : questionnaire) {
System.out.println(q);
System.out.println(q.getOptions());
String input = null; // you need to code this part
if(q.getAnswer().equals(input))
System.out.println("CORRECT!");
else
System.out.println("YOU IS STUPID!!!!");
}
}
}

Related

How to store objects in ArrayList and print it? [duplicate]

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
for loop without braces in java
(6 answers)
Closed 4 years ago.
i am working in my project and it is about a clinic , my class is appointment , and i have to let the user to enter the day, time, section, doctor name, patient name. and store it an ArrayList
i wrote the code but when i run the project there is no output and i don't know why :(
package appointments;
import java.util.Scanner;
import java.util.ArrayList;
public class Appointment {
public static void main(String[] args) {
ArrayList<Object> appointments = new ArrayList<>();
Scanner input = new Scanner (System.in);
System.out.println("enter day, time, section , doctor , you name in order to book appointment : ");
appointment xx = new appointment();
for (int i=0; i<5; ++i)
xx.setAppDay(input.nextLine());
xx.setAppTime(input.nextLine());
xx.setAppSection(input.nextLine());
xx.setAppDoctor(input.nextLine());
xx.setAppPatient(input.nextLine());
appointments.add(xx);
System.out.println(appointments);
}
public static class appointment {
public String appDay;
public String appTime;
public String appSection;
public String appDoctor;
public String appPatient;
public appointment(String appDay, String appTime, String appSection, String appDoctor, String appPatient) {
this.appDay = appDay;
this.appTime = appTime;
this.appSection = appSection;
this.appDoctor = appDoctor;
this.appPatient = appPatient;
}
public appointment() {
}
public void setAppDay(String appDay) {
this.appDay = appDay;
}
public void setAppTime(String appTime) {
this.appTime = appTime;
}
public void setAppSection(String appSection) {
this.appSection = appSection;
}
public void setAppDoctor(String appDoctor) {
this.appDoctor = appDoctor;
}
public void setAppPatient(String appPatient) {
this.appPatient = appPatient;
}
public String getAppDay() {
return appDay;
}
public String getAppTime() {
return appTime;
}
public String getAppSection() {
return appSection;
}
public String getAppDoctor() {
return appDoctor;
}
public String getAppPatient() {
return appPatient;
}
}
}
Your loop has no braces and you only instantiate one appointment. You wanted something like,
for (int i = 0; i < 5; ++i) {
appointment xx = new appointment();
xx.setAppDay(input.nextLine());
xx.setAppTime(input.nextLine());
xx.setAppSection(input.nextLine());
xx.setAppDoctor(input.nextLine());
xx.setAppPatient(input.nextLine());
appointments.add(xx);
}
Then you need to override toString() in appointment.
Currently the same appointment object is being added to the list, so the list would only have a single entry in it.
So move the object creation and addition to the list along with setting the appointment fields inside the for loop. Please add the curly braces correctly as currently only the
xx.setAppDay(input.nextLine())
is part of the for loop.
Also appointment shouldn't be a static class multiple objects need to be created.
You need to implement a toString() Method for this purpose. And print it like this.
public String toString(){
return this.appDay; // return the output you want, so build a String using your attributes
}
System.out.println(Arrays.toString(appointments));
Edit: And do what Elliott Frisch said.

ArrayChecker failure?

I have a problem with the following code:
Import java.util.ArrayList;
public class Car {
private String car;
private Car genCar = new Car();
ArrayList<String> allCars = new ArrayList<>();
public void setCar() {
genCar.setModel();
genCar.setCreator();
car = genCar.getModel() + "made by" + genCar.getCreator();
}
public void checkDouble() {
for (String search : allCars) {
while (search.equals(car)) {
setCar();
}
}
allCars.add(car);
}
public void repeater(){
for(int i = 0; i<52; i++){
setCar();
checkDouble();
}
}
}
Whenever I try to check for duplicates (which this code does) my program still puts the duplicate in the array when I actually try to avoid it this way.
Any solution so this works?
You do this:
public void checkDouble()
{
for (String search : allCars)
{
while (search.equals(car))
{
setCar();
}
}
allCars.add(car);
}
The problem with this is that, once you found a double, you generate a new car using setCar(), but you do not search the entire list again.
Do something like:
public void avoidDoubles()
{
while allCars.contains(car)
{
setCar(); // generate new, different car
}
allCars.add(car);
}
FWIW, you might want to change the name of some of the functions. I would call setCar() generateNewCar() or newCar().
I'm not sure what you're trying to do, but in checkDouble you are finding a duplicate and then adding it to the list.
If I understand you correctly, you don't need the loops, All you need to do is to use ArrayList.contains()
if(allCars.contains(someString))
{
System.err.println("Duplicate...");
} else
{
//setCar, addCar, etc.
}

How to deal with recursion in toString Java method?

My program is structured as follows: a class that represents an atomic concept which is essentially a String and another class that is made of a list of general concepts. Both classes extends the class Concept that is an abstract class, this means that in the list I could have both atomic concepts and intersection of concepts arbitrary nested.
Each concept, atomic or composed, is printed out by toString method.
Roughly speaking, this is based on this context-free grammar:
C : atom | (C and)+ C
Where C is the abstract class Concept, atom is AtomicConcept and (C and)+ C is Intersection.
This is the AtomicConcept class:
public class AtomicConcept extends Concept{
private String atomicConceptName;
public AtomicConcept(String c) {
this.atomicConceptName = c;
}
#Override
public String toString() {
return atomicConceptName;
}
}
This is che ConceptIntersection class:
import java.util.List;
public class ConceptIntersection extends Concept{
private List<Concept> list;
public ConceptIntersection(List<Concept> l) throws Exception {
if(l.size()>1)
{
this.list = l;
}
else
{
throw new Exception("Intersection needs at least two concepts!");
}
}
public String toString()
{
return Utils.conceptIntersection + Utils.lparen + Utils.splitConcepts(list) + Utils.rparen;
}
}
As you can see in toString function, I also created a method called splitConcepts that takes in input a list of general concepts and returns one string made of each concept separated by comma.
public static String splitConcepts(List<Concept> list)
{
String result = "";
for (Concept item : list) {
System.out.println(item);
result += item.toString() + comma;
}
result = result.substring(0, result.length() - 1);
return result;
}
Where is the problem?
I have trouble with this function because when I call a nested intersection in another one, this function never ends!
One example:
public static void main(String[] args) throws DLRException {
// TODO Auto-generated method stub
AtomicConcept atom = new AtomicConcept("one");
AtomicConcept at = new AtomicConcept("two");
List<Concept> list = new LinkedList<Concept>();
list.add(at);
list.add(atom);
DLRConceptIntersection intersection = new DLRConceptIntersection(list);
System.out.println(intersection); // works fine
list.add(intersection);
DLRConceptIntersection intersection2 = new DLRConceptIntersection(list);
System.out.println(intersection2); //loop never ends!
}
Is a correct approach to fix this problem?
You have a circular reference :
DLRConceptIntersection intersection = new DLRConceptIntersection(list);
list.add(intersection);
This causes the intersection's List to contain a reference to the same instance referred by intersection, which is why toString() run into infinite recursion.
I'm assuming you didn't intend intersection and intersection2 to share the same List.
You can avoid it if you create a copy of the List in the DLRConceptIntersection constructor:
public ConceptIntersection(List<Concept> l) throws Exception {
if(l.size()>1) {
this.list = new ArrayList<>(l);
} else {
throw new Exception("Intersection needs at least two concepts!");
}
}

Java - Access to variabe in other file [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have ArrayList and protected getter function in first class and function in second class, which extends first class. I do getList().size() in function, but getting 0. If I do myList.size() in first class, I getting right answer.
Code:
protected List<WrappedGameProfile> getList(){
return Text;
}
public int getServerInfoSize(){
return super.getList().size(); //returns 0
}
All code:
package ServerInfo;
//imports
public class ServerInfo extends JavaPlugin {
Logger log;
private List<WrappedGameProfile> Text = new ArrayList<WrappedGameProfile>();
FileConfiguration config;
protected String ConvertFormat(String format){
return format.replace("#0", ""+ChatColor.BLACK).replace("#1", ""+ChatColor.DARK_BLUE).replace("#2", ""+ChatColor.DARK_GREEN).replace("#3", ""+ChatColor.DARK_AQUA).replace("#4", ""+ChatColor.DARK_RED).replace("#5", ""+ChatColor.DARK_PURPLE).replace("#6", ""+ChatColor.GOLD).replace("#7", ""+ChatColor.GRAY).replace("#8", ""+ChatColor.DARK_GRAY).replace("#9", ""+ChatColor.BLUE).replace("#a", ""+ChatColor.GREEN).replace("#b", ""+ChatColor.AQUA).replace("#c", ""+ChatColor.RED).replace("#d", ""+ChatColor.LIGHT_PURPLE).replace("#e", ""+ChatColor.YELLOW).replace("#f", ""+ChatColor.WHITE);
}
protected List<WrappedGameProfile> getList(){
return Text;
}
protected void setText(List<WrappedGameProfile> Text){
this.Text = Text;
}
public void onEnable(){
log = getLogger();
log.info("GuiServerInfo activating...");
this.saveDefaultConfig();
config = getConfig();
ProtocolLibrary.getProtocolManager().addPacketListener(
new PacketAdapter(this, ListenerPriority.NORMAL,
Arrays.asList(PacketType.Status.Server.OUT_SERVER_INFO), ListenerOptions.ASYNC) {
#Override
public void onPacketSending(PacketEvent event) {
handlePing(event.getPacket().getServerPings().read(0));
}
}
);
for (int i = 0; i < config.getStringList("Text").size();i++){
Text.add(
new WrappedGameProfile(
"id" + i + 1,
ConvertFormat(config.getStringList("Text").get(i)))
);
}
log.info("GuiServerInfo active!");
}
#Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (sender.isOp()){
if (args.length > 0){
if (args[0].equalsIgnoreCase("set")){
Text.clear();
List<String> newConf = new ArrayList<String>();
for (int i = 1; i < args.length; i++){
Text.add(new WrappedGameProfile("id" + Text.size() + 1, ConvertFormat(args[i])));
newConf.add(args[i]);
log.info("Add ServerInfo: " + args[i]);
}
config.set("Text", newConf);
sender.sendMessage("Successful!");
return true;
}
}
return false;
} else {
sender.sendMessage("You not op!");
return true;
}
}
private void handlePing(WrappedServerPing ping) {
ping.setPlayers(Text);
}
public void onDisable(){
saveConfig();
log.info("GuiServerInfo disabled!");
}}
And:
package ServerInfo;
import java.util.ArrayList;
import java.util.List;
import com.comphenix.protocol.wrappers.WrappedGameProfile;
public class ServerInfoAPI extends ServerInfo {
public void setServerInfo(List<WrappedGameProfile> Text){
super.setText(Text);
super.log.info("Set new ServerInfo");
}
public void setServerInfo(String[] Text){
List<WrappedGameProfile> tmp = new ArrayList<WrappedGameProfile>();
for (int i = 0; i < Text.length; i++) {
tmp.set(i, new WrappedGameProfile("id" + i + 1, ConvertFormat(Text[i])));
}
super.setText(tmp);
super.log.info("Set new ServerInfo");
}
public void insertServerInfoString(String str, int num){
getList().set(num, new WrappedGameProfile("id" + num, ConvertFormat(str)));
super.log.info("Add new ServerInfo - num:" + num + ", Text:" + str);
}
public void addServerInfoString(String str){
super.getList().add(new WrappedGameProfile("id" + super.getList().size() + 1, ConvertFormat(str)));
super.log.info("Add new ServerInfo: " + str);
}
public int getServerInfoSize(){
return super.getList().size();
}
public String getServerInfoString(int num){
return super.getList().get(num).getName();
}
public int getServerInfoStringNum(WrappedGameProfile pr){
return super.getList().indexOf(pr);
}
}
Just your terminology alone shows a serious lack of understanding of things like Objects, Classes, Packages, etc. you need to read up on some introductory tutorials.
To answer the question it sounds like you have created a new instance inheriting from a super class. Because it is a new instance the list is not shared, so changes you make in one class do not get seen.
To share one list between multiple objects you need to pass the list object from one to another.
Don't try to globalize variables. Instead call public methods of the class that holds the variable that will allow other objects to query its state or make controlled change to its state.
I agree also with the others: it sounds as if you're misusing inheritance, since this is not a problem that should be solved with inheritance, but only your code (which we haven't seen at the time of this writing) will tell us for sure.
Regarding:
No, i have just one List
No, if you're using inheritance, then you have more than one List. Again don't try to solve this with inheritance.
Why don't you have a
private List<WrappedGameProfile> text = new ArrayList<WrappedGameProfile>();
public List<WrappedGameProfile> getText() {
return text;
}
in your super class?
than your code will be :
public int getServerInfoSize(){
return getText().size();
}
and please do camelcasing correct, the variable Text has to be text.

Java-How do I call a class with a string?

I am a beginner programmer and this is my first question on this forum.
I am writing a simple text adventure game using BlueJ as a compiler, and I am on a Mac. The problem I ran into is that I would like to make my code more self automated, but I cannot call a class with a string. The reason I want call the class and not have it all in an if function is so that I may incorporate more methods.
Here is how it will run currently:
public class textadventure {
public method(String room){
if(room==street){street.enterRoom();}
}
}
public class street{
public enterRoom(){
//do stuff and call other methods
}
}
The if statement tests for every class/room I create. What I would like the code to do is automatically make the string room into a class name that can be called. So it may act like so:
Public method(string room){
Class Room = room;
Room.enterRoom();
}
I have already looked into using Class.forName, but all the examples were too general for me to understand how to use the function. Any help would be greatly appreciated, and if there is any other necessary information (such as more example code) I am happy to provide it.
-Sebastien
Here is the full code:
import java.awt.*;
import javax.swing.*;
public class Player extends JApplet{
public String textOnScreen;
public void start(){
room("street1");
}
public void room(String room){
if(room=="street1"){
textOnScreen=street1.enterRoom();
repaint();
}
if(room=="street2"){
textOnScreen=street2.enterRoom();
repaint();
}
}
public void paint(Graphics g){
g.drawString(textOnScreen,5,15);
}
}
public abstract class street1
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on a street running from North to South.";
return textToScreen;
}
}
public abstract class street2
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on another street.";
return textToScreen;
}
}
Seeing as you are rather new to programming, I would recommend starting with some programs that are simpler than a full-fledged adventure game. You still haven't fully grasped some of the fundamentals of the Java syntax. Take, for example, the HelloWorld program:
public class HelloWorld {
public static void main(String[] args) {
String output = "Hello World!"
System.out.println(output);
}
}
Notice that public is lowercased. Public with a capital P is not the same as public.
Also notice that the String class has a capital S.* Again, capitalization matters, so string is not the same as String.
In addition, note that I didn't have to use String string = new String("string"). You can use String string = "string". This syntax runs faster and is easier to read.
When testing for string equality, you need to use String.equals instead of ==. This is because a == b checks for object equality (i.e. a and b occupy the same spot in memory) and stringOne.equals(stringTwo) checks to see if stringOne has the same characters in the same order as stringTwo regardless of where they are in memory.
Now, as for your question, I would recommend using either an Enum or a Map to keep track of which object to use.
For example:
public class Tester {
public enum Location {
ROOM_A("Room A", "You are going into Room A"),
ROOM_B("Room B", "You are going into Room B"),
OUTSIDE("Outside", "You are going outside");
private final String name;
private final String actionText;
private Location(String name, String actionText) {
this.name = name;
this.actionText = actionText;
}
public String getActionText() {
return this.actionText;
}
public String getName() {
return this.name;
}
public static Location findByName(String name) {
name = name.toUpperCase().replaceAll("\\s+", "_");
try {
return Enum.valueOf(Location.class, name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private Location currentLocation;
public void changeLocation(String locationName) {
Location location = Location.findByName(locationName);
if (location == null) {
System.out.println("Unknown room: " + locationName);
} else if (currentLocation != null && currentLocation.equals(location)) {
System.out.println("Already in room " + location.getName());
} else {
System.out.println(location.getActionText());
currentLocation = location;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
tester.changeLocation("room a");
tester.changeLocation("room b");
tester.changeLocation("room c");
tester.changeLocation("room b");
tester.changeLocation("outside");
}
}
*This is the standard way of formating Java code. Class names are PascalCased while variable names are camelCased.
String className=getClassName();//Get class name from user here
String fnName=getMethodName();//Get function name from user here
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(className);// get the Class
Object inst = thisClass.newInstance();// get an instance
// get the method
Method fn = thisClass.getDeclaredMethod(fnName, params);
// call the method
fn.invoke(inst, paramsObj);
The comments below your question are true - your code is very rough.
Anyway, if you have a method like
public void doSomething(String str) {
if (str.equals("whatever")) {
// do something
}
}
Then call it like
doSomething("whatever");
In Java, many classes have attributes, and you can and will often have multiple instances from the same class.
How would you identify which is which by name?
For example
class Room {
List<Monster> monsters = new ArrayList <Monster> ();
public Room (int monstercount) {
for (int i = 0; i < monstercount; ++i)
monsters.add (new Monster ());
}
// ...
}
Monsters can have attributes, and if one of them is dead, you can identify it more easily if you don't handle everything in Strings.

Categories