I found that this worked :)
I found a way to make it work. Instead of this:
for(int i=0; i<alla.size(); i++){
if(alla.get(i).getClass().getName().equals("Aktie")){
alla.get(i).setKurs(0.0);
}
}
I got this to work:
for(Värdesak v : alla){
if(v instanceof Aktie){
((Aktie)v).setKurs(0.0);
}
}
I can't to figure out whats wrong with this one.. I have an arraylist of different objects, and I have a button in my program that is called "stock market crash" which should set all existing stocks course(have no clue what word i'm looking for here) in my arraylists to 0.0. shouldn't it be like this alla.get(i).setKurs(0.0); when I've found one stock object in my arraylist if the stock class (which is a subclass) have an public void setKurs(double kurs) { this.kurs = kurs; }?
I'll post my code here:
This is my button
class börsLyssna implements ActionListener{
public void actionPerformed(ActionEvent ave){
for(int i=0; i<alla.size(); i++){
if(alla.get(i).getClass().getName().equals("Aktie")){
alla.get(i).setKurs(0.0);
}
}
}
}
__
abstract class Värdesak{
private String namn;
protected Värdesak(String namn){
this.namn = namn;
}
public String getNamn(){
return namn;
}
abstract public double getVärde();
public String toString(){
return namn + ", "+ "värde: "+(getVärde()*1.25);
}
}
class Aktie extends Värdesak{
private int antal;
private double kurs;
public Aktie(String namn, int antal, double kurs){
super(namn);
this.antal = antal;
this.kurs = kurs;
}
public double getVärde(){
return (antal*kurs);
}
public String toString(){
return super.toString()+", antal: "+antal+" med en kurs på: "+kurs;
}
public void setKurs(double kurs) {
this.kurs = kurs;
}
public double getKurs() {
return kurs;
}
}
I believe that the (Class).getName() method returns the fully qualified class name (including the package).
For example, from the JDK 1.8 docs, the getName() comments contains this example:
String.class.getName()
returns "java.lang.String"
You're testing for the Class name without the package hierarchy preface.
Instead of
alla.get(i).getClass().getName().equals("Aktie")
try
alla.get(i) instanceof Aktie
The alla.get(i).getClass().getName() will return the package and name of the class, e.g. java.lang.String instead of just String.
Since you don't show us how alla is populated we can't tell if any Akties are even in it. There are a lot of suggested ways to fix this. Here's some debugging code that will let you clearly know where the problem is and when it's fixed.
class börsLyssna implements ActionListener{
public void actionPerformed(ActionEvent ave){
for(int i=0; i<alla.size(); i++){
if(alla.get(i).getClass().getName().equals("Aktie")){
System.out.println("Attempting to set kurs to 0.0 at i=" + i");//TODO remove debugging code
alla.get(i).setKurs(0.0);
}
}
}
}
Personally I think alla.get(i) instanceof Aktie will fix it. Though I think your life will be easier if you didn't put different types of objects in a collection in the first place. Wouldn't it be nice if you could just call set() on everything in there?
Related
The following code is the solution code, which declares an abstract class with one absract subclass (that in turn has two subclasses) and another subclass. Because the method setScore() has to be implemented in three different ways, and the objecttype differs for each case, I'm presuming we use the parameter P to define it.
public abstract class Vak<P> implements EvaluatieSpecificatie,
Comparable<Vak> {
private VakInfo vak;
public abstract void setScore(P parameter);
public Vak(VakInfo v) {
vak = v;
}
public String getVakNaam() {
return vak.getNaam();
}
public int getStudiepunten() {
return vak.getStudiepunten();
}
public String getVakcode() {
return vak.getVakcode();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(vak);
if (isGeslaagd()) {
sb.append(" C");
} else {
sb.append(" niet geslaagd - moet hernomen worden");
}
return sb.toString();
}
#Override
public int compareTo(Vak v) {
// sorteren van vakken op basis van studiepunten
// this < v --> neg waarde teruggeven
// this > v --> pos waarde teruggeven
// this = v --> 0 teruggeven
return this.getStudiepunten() - v.getStudiepunten();
}
}
Now, what I don't understand is how exactly this class ClassName"<"Parameter">" thing works, when to use it, or what exactly its called. I've tried to look it up, but I can't seem to find any information on it. Could anyone explain to me what exactly this is, and how/when it's supposed to be used? (Or link me in the right direction), perhaps by giving a simple example (since I'm not sure if asking for code is required).
I'm terribly sorry if this question isn't appropriate, but I'd really like to understand, so here goes.
Appereantly it's called a generic type. Thank you #HRgiger.
https://docs.oracle.com/javase/tutorial/java/generics/types.html
I want to try a simple implementation of phonebook with arraylist in java.
First I made a class contains what the info. needed and second I want have another class which have methods like getting info and printing them.
and because I want to use array list this is what I've done so far, but the 'print' method keep giving me the error in for loop, is there any one who can help me to optimize my code and why I have this error.
this is the first class :
public class PhoneBook {
long number;
String name;
.
.
.
.
getter() and setter();
}
The second class with methods:
public class PhoneBookMethods {
ArrayList<PhoneBook> phoneBooks = new ArrayList<PhoneBook>();
public void getInfo(PhoneBook phoneBooks)
{
.
.
.
}
public void print(PhoneBook phoneBooks)
{
for (PhoneBook p: phoneBooks) {// this is where I got the error
//foreach not applicable to type 'PhoneBook'
System.out.print(p.getName());
....
}
}
}
In your for-each loop, change
for (PhoneBook p: phoneBooks)
to
for (PhoneBook p: this.phoneBooks)
so that you would be accessing the phoneBooks arraylist, not the argument of the print method.
EDIT:
You can use the "this" keyword to make your code much more "explicit".
For the example, in your case you have an argument called phoneBooks that has the same name as your ArrayList (member variable). So to explicitly differentiate between the two of them, use this.phonebooks to access the member variable phoneBooks(the ArrayList), and use phoneBooks to refer to the argument.
If you want to use instance variable phoneBooks then no need to pass any param in the method print().
public void print()
{
for (PhoneBook p: phoneBooks) {// this is where I got the error
//foreach not applicable to type 'PhoneBook'
System.out.print(p.getName());
....
}
}
OR if you really want to pass param rename the param name
public void print(ArrayList<PhoneBook> phoneBookList)
{
for (PhoneBook p: phoneBookList) {// this is where I got the error
//foreach not applicable to type 'PhoneBook'
System.out.print(p.getName());
....
}
}
public void print(PhoneBook phoneBooks)
Your parameter phoneBooks masks the field (the array) also named phoneBooks. So compiler tries to treat parameter as list and failes.
Actually at first you have some design issues. The way you think what is a PhoneBook is invalid. You should consider a phonebook something holds several phones on it. Therefore, you may have a phone class like below:
public class Phone {
private String number;
private String name;
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And a phonebook class responsible for holding those phone objects:
public class PhoneBook extends ArrayList<Phone> {
#Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
for (Phone phone : this) {
stringBuilder.append("----------------------------\n");
stringBuilder.append("Name:" + phone.getName() + "\n");
stringBuilder.append("Number:" + phone.getNumber() + "\n");
}
return stringBuilder.toString();
}
}
It is a arraylist of Phone, nothing more. Thus, you can add or remove a phone directly via phone book. This is how to use it:
public class MAIN {
public static void main(String[] args) {
Phone myPhone = new Phone();
myPhone.setName("Eray");
myPhone.setNumber("0533XXXXXXX");
Phone girlfriendPhone = new Phone();
girlfriendPhone.setName("Canan");
girlfriendPhone.setNumber("0544XXXXXXX");
Phone yourPhone = new Phone();
yourPhone.setName("Bita Mirshafiee");
yourPhone.setNumber("0599XXXXXXX");
PhoneBook phoneBook = new PhoneBook();
phoneBook.add(myPhone);
phoneBook.add(girlfriendPhone);
phoneBook.add(yourPhone);
System.out.println(phoneBook);
}
}
Finally, this is the output:
----------------------------
Name:Eray
Number:0533XXXXXXX
----------------------------
Name:Canan
Number:0544XXXXXXX
----------------------------
Name:Bita Mirshafiee
Number:0599XXXXXXX
I'm stuck with a problem here. I want to change the setter from a attribute from the superclass (parent class) in my subclass (child) however when I overide this method in my subclass I can't access my private attributes from the supperclass. And the point is, they have to stay private.
Superclass (problem: setMinimumVoorraad(int voorraad);)
package domein;
public abstract class Artikel implements Weegbaar
{
private String omschrijving;
private double prijs;
private int aantalInStock;
private int minimumVoorraad;
public Artikel(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad)
{
this.setOmschrijving(omschrijving);
this.setPrijs(prijs);
this.setAantalInStock(aantalInStock);
this.setMinimumVoorraad(minimumVoorraad);
}
#Override
public String toString()
{
String output = String.format(" \n omschrijving: %s \n prijs: %f \n In stock %d (minimumvoorraad = %d) \n", this.omschrijving, this.prijs, this.aantalInStock, this.minimumVoorraad);
return output;
}
//----Getters----
public String getOmschrijving() {
return omschrijving;
}
public double getPrijs() {
return prijs;
}
public int getAantalInStock() {
return aantalInStock;
}
public int getMinimumVoorraad() {
return minimumVoorraad;
}
//----Setters----
public void setOmschrijving(String omschrijving) {
this.omschrijving = omschrijving;
}
public void setPrijs(double prijs) {
this.prijs = prijs;
}
public void setAantalInStock(int aantalInStock) {
this.aantalInStock = aantalInStock;
}
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 2)
this.minimumVoorraad = 3;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Subclass
package domein;
public class Food extends Artikel
{
private String houdbaarheidsDatum;
private double nettoGewicht;
public Food(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad, String houdbaarheidsDatum, double nettoGewicht)
{
super(omschrijving, prijs, aantalInStock, minimumVoorraad);
this.setHoudbaarheidsDatum(houdbaarheidsDatum);
this.setNettoGewicht(nettoGewicht);
}
#Override
public boolean isWeegbaar()
{
return true;
}
//----Getters----
public String getHoudbaarheidsDatum() {
return houdbaarheidsDatum;
}
public double getNettoGewicht() {
return nettoGewicht;
}
//----Setters----
public void setHoudbaarheidsDatum(String houdbaarheidsDatum) {
this.houdbaarheidsDatum = houdbaarheidsDatum;
}
public void setNettoGewicht(double nettoGewicht) {
this.nettoGewicht = nettoGewicht;
}
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 5)
this.minimumVoorraad = 6;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Someone who can help me?
Thanks in advance.
One possibility is to implement the subclass's setter in terms of the superclass's setter (which, presumably, you do have access to).
For example, assuming the setter is setFoo, then the subclass's version might be:
public void setFoo(Foo f) {
// Do subclass stuff pre-setting, if any
super.setFoo(f);
// Do subclass stuff post-setting, if any
}
The answer given above by NPE is absolutely the best way to go about solving this problem. It is elegant and honors basic inheritance contracts between superclass and subclass. Even in your original post, the subclass is actually more restrictive than the superclass, so doing something like:
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad <= 5)
super.setMinimumVoorraad(6);
else
super.setMinimumVoorraad(minimumVoorraad);
}
exactly as NPE suggested would probably work. (Note how I modified your if test. Not sure if it's a typo, but in the original implementation 5 would be a valid minimum, but input like 4 would set it to 6.)
Other (possibly acceptable) patterns would be to:
Make the members in your Parent class protected, which would give visibility. (Realize that you did mention a private restriction; this pattern is solely mentioned to provide a more complete overall answer.)
Delegate the validation logic to another method (that is non-private). This way the child can override the validation method.
And now on to the (probably unacceptable) pattern of using Java reflection:
#Override
public void setMinimumVoorraad(int minimumVoorraad) {
try {
Field field = this.getClass().getSuperclass().getDeclaredField("minimumVoorraad");
field.setAccessible(true);
if(minimumVoorraad <= 5)
field.set(this, 6);
else
field.set(this, minimumVoorraad);
field.setAccessible(false);
}
catch(NoSuchFieldException | IllegalAccessException e) {
// do something
}
}
It's worth noting that if you never ever do this in your entire life you will probably be the better for it. Not only does it completely break all contracts, but it relies on hard-coded Strings to do field name lookups, which in and of itself is pretty painful. But it does exist. And no good answer (already given above by NPE) would be complete without an example of how not to do something...
This question already has answers here:
Non-static variable cannot be referenced from a static context
(15 answers)
Closed 9 years ago.
I am having an issue with this error, while trying to write a method that lists all names in a specific class. (error at bottom) I have tried a few things but for the life of me, cannot figure it out. Please help, thanks.
Class Cat:
public class Cat
{
// instance variables
private String name;
private int yearOfBirth;
private int weightInKilos;
public Cat() {
setName("");
setYearOfBirth(0);
setWeightInKilos(0);
}
/**
*
*/
public Cat(String newName, int newYearOfBirth, int newWieghtInKilos )
{
setName(newName);
setYearOfBirth(newYearOfBirth);
setWeightInKilos(newWieghtInKilos);
}
public String getName(){
return name;
}
public int getYearOfBirth(){
return yearOfBirth;
}
public int getWieghtInKilos(){
return weightInKilos;
}
public void setName(String newName){
if (newName != null ){
name = newName;
}
else{
System.out.println("Invalid Name");
}
}
public void setYearOfBirth(int newYearOfBirth){
if (yearOfBirth >= 0){
yearOfBirth = newYearOfBirth;
}
else{
System.out.println("Year Of Birth must not be negative!");
}
}
public void setWeightInKilos(int newWeightInKilos){
if (weightInKilos >= 0){
weightInKilos = newWeightInKilos;
}
else{
System.out.println("Weight must not be negative!");
}
}
}
Class Cattery:
import java.util.ArrayList;
public class Cattery
{
// instance variables - replace the example below with your own
private ArrayList <Cat> cats;
private String businessName;
/**
* Constructor for objects of class Cattery
*/
public Cattery(String NewBusinessName)
{
cats = new ArrayList <Cat>();
NewBusinessName = businessName;
}
public void addCat(Cat newCat){
cats.add(newCat);
}
public void indexDisplay(int index) {
if((index >= 0) && (index <= cats.size()-1)) {
System.out.println(index);
}
else{
System.out.println("Invalid index position!");
}
}
public void removeCat(int indexremove){
if((indexremove >= 0) && (indexremove <= cats.size()-1)) {
cats.remove(indexremove);
}
else{
System.out.println("Invalid index position!");
}
}
public void displayNames(){
System.out.println("The current guests in Puss in Boots Cattery:");
for(Cat catNames : cats ){
System.out.println(Cat.getName()); //ERROR; non static method cannot be referenced from a static context..wtf
}
}
}
Please help, thanks
When you have an instance method, you need to call it on a specific instance of the class.
Here:
System.out.println(Cat.getName());
you're trying to call it on the Cat class itself. You want:
for (Cat cat : cats ) {
System.out.println(cat.getName());
}
Note that I've changed the name of the iteration variable from catNames to cat as well - because the value is just a reference to "the cat we're looking at at the moment". It's not the cat name, nor is it multiple cats (or cats names) - it's a single cat. It's very important to name variables carefully - it can help correct code to look correct, and incorrect code to look incorrect. It doesn't make sense to call getName() on a variable called catNames... (what is the name of a collection of names?) but it absolutely makes sense to call it on a variable called cat.
Another warning bell from your original code was that the body of your for loop didn't use the iteration variable - that almost always suggests that something's wrong. The fixed version does, of course.
Use:
System.out.println(catNames.getName());
getName is non static function, so you need to use it on an instance of that class, like you have in the cats list.
Cat.getName() this line means getName() should be static method in Cat class, but's not as such.
so access getName() method by instacne .
System.out.println(catNames.getName());
for (Cat cat : cats) {
System.out.println(Cat.getName());
}
Here you need to use cat, not Cat. So use
for (Cat cat : cats) {
System.out.println(cat.getName());
}
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.