Depending on an Input given in another class, this class has to retrieve a variable from one of 4 classes in which that variable is to be found. Eg. if the input has been an s the variable this class is looking for is found in Sumup.counter whereas when the input has been an a the variable it needs, is to be found in Abstract.counter etc etc, in order to fill an Array. In one of these 4 different classes it has to pick up 5 different variables. So in order to avoid lots of extra programming I want to replace these class names Sumup and Abstract with a variable. So it has to look like anything like this Variable.counter, Variable.part1 etc. In which Variable can be either Sumup or Abstract (or Multiply or Divide).
Anyone a suggestion how to do this?
public class Erroranalysis {
public static int[][] wrongcalculations = new int[5][Numberofcalculations.numcalc];
static int runner = 0;
static String routine;
public static void main(String[] args)
{
switch (kindofcalculation.choice)
{
case "s":
routine = "Sumup";
break;
case "a":
routine = "Abstract";
break;
case "m":
routine = "Multiply";
break;
case "d":
routine = "Divide";
break;
}
if (routine.counter <= Numberofcalcluations.numcalc)
{
wrongcalculations[0][runner] = routine.counter;
wrongcalculations[1][runner] = routine.part1;
wrongcalculations[2][runner] = routine.part2;
wrongcalculations[3][runner] = routine.result;
wrongcalculations[4][runner] = routine.answer;
runner++;
}
}
}
you can opt for a base abstract class and make an array of that class:
class Base{
public int counter = 0;
}
class Sumup extends Base{
}
class Abstract extends Base{
}
public class Erroranalysis {
public static int[][] wrongcalculations = new int[5][Numberofcalculations.numcalc];
static int runner = 0;
static Base routine;
static Sumup sumup;
static Abstract abs;
public static void main(String[] args)
{
sumup = new Sumup();
abs = new Abstract();
// possibly, this part won't be in main, but in some for loop of another method
switch (kindofcalculation.choice)
{
case "s":
routine = sumup;
case "a":
routine = abs;
}
if (routine.counter <= Numberofcalcluations.numcalc)
{
wrongcalculations[0][runner] = routine.counter;
wrongcalculations[1][runner] = routine.part1;
wrongcalculations[2][runner] = routine.part2;
wrongcalculations[3][runner] = routine.result;
wrongcalculations[4][runner] = routine.answer;
runner++;
}
}
}
Related
I have created an array which I wanted to control from main. My code runs, but I don't know how to add integers to the array from the main class. Also as each ConcreteSubject has its own storage array, how would i change this to store them all in the same array?
public class ConcreteSubject extends AbstractSpy
{
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy s) {
if (i < spies.length) {
spies[i] = s;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass
{
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
spies.addSpy(spies);
}
}
It seems like your program logic is a little borked. This bit in particular doesn't make much sense:
***AbstractSpy spies = new AbstractSpy() {
#Override
public void addSpy(AbstractSpy spies) {
}
};
cs.addSpy(cs);
***spies.addSpy(spies);
What you're doing is creating TWO AbstractSpy instances, one named cs and one named spies. On that last line you're adding spies to itself! That doesn't help you at all.
Note that AbstractSpy is the most granular unit in your setup - it shouldn't have an addSpy() method and its own internal array, it should be the thing that's added to something else's array!
Here's the same code, but cleaned up a bit:
public abstract class AbstractSpy { }
public class ConcreteSpy extends AbstractSpy { }
public class ConcreteSubject {
private AbstractSpy[] spies = new AbstractSpy[10];
private int i = 0;
public void addSpy(AbstractSpy spy) {
if (i < spies.length)
{
spies[i] = spy;
System.out.println("spy added at index " + i);
i++;
}
}
}
public class TestClass {
public static void main(String[] args) {
ConcreteSubject cs = new ConcreteSubject();
AbstractSpy spy = new ConcreteSpy();
cs.addSpy(spy);
}
}
The big difference here is that ConcreteSpy is an implementation of AbstractSpy that you can add to your ConcreteSubject's array of spies. I think you might have been confused by Java's insistence that you can't create an instance of an abstract class on its own unless you supply an anonymous class that inherits from the abstract class.
package test.arraylist;
import java.util.Scanner;
public class TestArraylist {
static Scanner keyboard = new Scanner (System.in);
static int how_many;
public static void main(String[] args) {
menu();
}
public static void menu()
{
System.out.println("1.L2C");
System.out.println("2.M2R");
int menu = keyboard.nextInt();keyboard.nextLine();
switch (menu){
case 1:
NewClass l2c = new NewClass();
System.out.println("How many:");
how_many = keyboard.nextInt();keyboard.nextLine();
for (int i=0;i<how_many;i++){
System.out.println("Insert values:");
l2c.l2c.add(keyboard.nextLine());
System.out.println("values:"+l2c.getL2c());
}
break;
case 2:
NewClass r2p = new NewClass();
System.out.println("How many:");
how_many = keyboard.nextInt();keyboard.nextLine();
for (int i=0;i<how_many;i++){
System.out.println("Insert values:");
r2p.r2p.add(keyboard.nextLine());
System.out.println("values:"+r2p.getR2p());
}
break;
}
}
public static void seats(){
System.out.println("values:"+r2p.getR2p()); // Error
System.out.println("values:"+l2p.getR2p()); // Error
}
}
---------------------------CLASS-----------------------
package test.arraylist;
import java.util.ArrayList;
public class NewClass {
ArrayList<String> l2c = new ArrayList<>();
ArrayList<String> r2p = new ArrayList<>();
public ArrayList<String> getL2c() {
return l2c;
}
public void setL2c(ArrayList<String> l2c) {
this.l2c = l2c;
}
public ArrayList<String> getR2p() {
return r2p;
}
public void setR2p(ArrayList<String> r2p) {
this.r2p = r2p;
}
}
I'm in java for only 2 weeks
In a few words, I'm going to explain what I'm trying to do.
I am creating an ArrayList, after this user is entering
values to Arraylist.
Once everything is done, I want to access data from another method and to make some math operations, I realized that I should use some sort of return, I have tried to do this, but it does not work.
I am definitely doing something wrong.Pls help to sort this out.I spent 2 days on this.
It seems what you need is the composition of the NewClass into your Main class i.e.TestArraylist , Read composition in java composition-in-java-example
Now your code should be like this,
public class TestArraylist {
static NewClass newClass = new NewClass();
---------
--------
public static void menu(){
case 1:
ArrayList<String> l2c = newClass.getL2c(); //this way you can access the data
System.out.println("How many:");
how_many = keyboard.nextInt();keyboard.nextLine();
for (int i=0;i<how_many;i++){
System.out.println("Insert values:");
l2c.add(keyboard.nextLine()); //here you need only the instance variable to add the data into the arraylist.
System.out.println("values:"+l2c.toString()); //to print the data
}
break;
//Same way you should modify the case2 as well.
case 2:
ArrayList<String> r2p = newClass.getR2p();
System.out.println("How many:");
how_many = keyboard.nextInt();keyboard.nextLine();
for (int i=0;i<how_many;i++){
System.out.println("Insert values:");
r2p.add(keyboard.nextLine());
System.out.println("values:"+r2p.toString());
}
break;
Now that composite object will be accesible in you below method because we have declared it static.
public static void seats(){
System.out.println("values:"+newClass.getR2p()); // not throw any error
System.out.println("values:"+newClass.getR2p()); // not throw any error
}
Also your Newclass should be defined like this,
public class NewClass {
private ArrayList<String> l2c = new ArrayList<String>();
private ArrayList<String> r2p = new ArrayList<String>();
public ArrayList<String> getL2c() {
return l2c;
}
public void setL2c(ArrayList<String> l2c) {
this.l2c = l2c;
}
public ArrayList<String> getR2p() {
return r2p;
}
public void setR2p(ArrayList<String> r2p) {
this.r2p = r2p;
}
}
There are many things to be corrected but as of now to make your programm work , this should suffice.
If you call seats(), you will have an error because those variables are not declared within the proper scope. To make r2p and l2c available within that method, move the variable declarations outside of the method (below the class declaration, before main()) with the initializer private static NewClass newClass;. Feel free to assign a value as needed, or employ optionals (but considering you’ve only been doing Java for 2 weeks, stay away from optionals; just make sure you assign a value).
Edit: Use static modifier on the variables, since you’re accessing from a static context.
I have the object numberlist that i created in create() method and i want to access it so i can use it in the question() method.
Is there another way to do this that I probably missed? Am I messing something up? If not, how should I do this to get the same functionality as below?
private static void create() {
Scanner input = new Scanner(System.in);
int length,offset;
System.out.print("Input the size of the numbers : ");
length = input.nextInt();
System.out.print("Input the Offset : ");
offset = input.nextInt();
NumberList numberlist= new NumberList(length, offset);
}
private static void question(){
Scanner input = new Scanner(System.in);
System.out.print("Please enter a command or type ?: ");
String c = input.nextLine();
if (c.equals("a")){
create();
}else if(c.equals("b")){
numberlist.flip(); \\ error
}else if(c.equals("c")){
numberlist.shuffle(); \\ error
}else if(c.equals("d")){
numberlist.printInfo(); \\ error
}
}
While interesting, both of the answers listed ignored that fact that the questioner is using static methods. Thus, any class or member variable will not be accessible to the method unless they are also declared static, or referenced statically.
This example:
public class MyClass {
public static String xThing;
private static void makeThing() {
String thing = "thing";
xThing = thing;
System.out.println(thing);
}
private static void makeOtherThing() {
String otherThing = "otherThing";
System.out.println(otherThing);
System.out.println(xThing);
}
public static void main(String args[]) {
makeThing();
makeOtherThing();
}
}
Will work, however, it would be better if it was more like this...
public class MyClass {
private String xThing;
public void makeThing() {
String thing = "thing";
xThing = thing;
System.out.println(thing);
}
public void makeOtherThing() {
String otherThing = "otherThing";
System.out.println(otherThing);
System.out.println(xThing);
}
public static void main(String args[]) {
MyClass myObject = new MyClass();
myObject.makeThing();
myObject.makeOtherThing();
}
}
You would have to make it a class variable. Instead of defining and initializing it in the create() function, define it in the class and initialize it in the create() function.
public class SomeClass {
NumberList numberlist; // Definition
....
Then in your create() function just say:
numberlist= new NumberList(length, offset); // Initialization
Declare numberList outside your methods like this:
NumberList numberList;
Then inside create() use this to initialise it:
numberList = new NumberList(length, offset);
This means you can access it from any methods in this class.
I have an interface and these methods:
public interface Form {
public void setFirstName (String value);
public void setLastName (String value);
public void setGender (String value);
}
Can I call these methods randomly on an objet? Something like:
form.randomMethodFromFormInterface(String randomString);
Is it actually possible? Just to clarify, I would like to fillout the form randomly: sometimes just the last name, sometimes just the first name, sometimes just the gender.
Random rand = new Random();
switch (rand.nextInt(3)) {
case 0: myForm.setFirstName(myFirstName); break;
case 1: myForm.setLastName(myLastName); break;
case 2: myForm.setGender(myGender); break;
default: throw new IllegalStateException();
}
Couldn't you use Random to pick from 0-2, and then depending on that value call the corresponding method?
Could you make another method in the interface that generates a random number and calls a method based on that number? Although I would bet there's an easier way to do this than creating an interface for it.
Here a general way, using reflection:
private static Random r = new Random();
public static void callRandomMethod(Object target, Class<?> iface, Object ... arguments) {
List<Method> methods = findFittingMethods(iface, arguments);
Method m = methods.get(r.nextInt(methods.size()));
m.invoke(target, arguments);
}
public List<Method> findFittingMethods(Class<?> iface, Object ... arguments
Method[] allMethods = iface.getMethods();
List<Method> fittingMethods = new ArrayList<Method>();
findMethodLoop:
for(Method candidate : allMethods) {
Class<?>[] argumentTypes = candidate.getArguments();
if(argumentTypes.length != arguments.length) {
continue;
}
// check argument types
for(int i = 0; i < argumentTypes.length; i++) {
if(arguments[i] == null) {
if(argumentTypes[i].isPrimitive()) {
// null can't be passed to a primitive argument.
continue findMethodLoop;
}
else {
// ... but to every other argument type.
continue; // check next argument
}
}
if(argumentTypes[i].isInstance(arguments[i])) {
continue; // check next argument
}
if(argumentTypes[i].isPrimitive()) {
// hack to check if we have the right wrapper class
try {
Array.set(Array.newInstance(argumentTypes[i], 1), 0, arguments[i]);
continue; // check next argument
}
catch(ArrayStoreException ex) {
continue findMethodLoop;
}
}
// wrong type
continue findMethodLoop;
}
// now we found a method which would accept the arguments, put it into the list.
fittingMethods.add(candidate);
}
return fittingMethods;
}
Of course, if you do this often, you would not create the list of methods for every call, but only once, and reuse it then. (And if you only have a known interface with a low number of methods, use the switch statement instead, like others have recommended.)
You can place the various method names in an array structure.
Then choose a random index within the scope of the array.
Then use reflection to actually call the method using the randomly chosen name from the previous step
Why not make the following method:
public static void randomMethodFromFormInterface(Form form, String value) {
switch(random.nextInt(3) {
case 0:
form.setFirstName(value);
break;
case 1:
form.setLastName(value);
break;
case 2:
form.setGenderName(value);
break;
}
}
You can put it in a utility class. random here is, of course, an instance of java.util.Random.
Can I call these methods randomly on
an objet?
Yes, this is possible with Reflection. The randomness is not implemented in this example (I assume that you can easily do this with a random int) and all methods are called without knowing how they are named or how many methods are available. For simplicity the example assumes that the parameter is only a String (like in your example). Of course, you must instantiate a class which implements Form:
Class thisClass = Class.forName("FormImpl");
Object o = thisClass.newInstance();
Method[] methods = thisClass.getDeclaredMethods();
for(Method m : methods)
{
m.invoke(o, "test");
}
You could do something like below. However, I am not sure if I really like the idea of calling methods in an interface randomly. It breaks the contract in a way and sounds like a bad design idea in my opinion.
import java.util.Random;
public class RandomInterfaceImpl implements RandomInterface {
private Random rnd;
public RandomInterfaceImpl(){
rnd = new Random();
}
#Override
public void setFirstName(String value) {
System.out.println("called setFirstName");
}
#Override
public void setLastName(String value) {
System.out.println("called setLastName");
}
#Override
public void setGender(String value) {
System.out.println("called setGender");
}
#Override
public void getNextRandomMethod(String value) {
int nextRand = rnd.nextInt(3);
switch(nextRand){
case 0: setFirstName(value); break;
case 1: setLastName(value); break;
case 2: setGender(value); break;
}
}
}
public static void main(String[] args) {
RandomInterface myInterface = new RandomInterfaceImpl();
myInterface.getNextRandomMethod("Foo");
myInterface.getNextRandomMethod("Foo");
myInterface.getNextRandomMethod("Foo");
}
prints:-
called setFirstName
called setLastName
called setLastName
Why is this int switch valid:
public class Foo {
private final static int ONE = 1;
private final static int TWO = 2;
public static void main(String[] args) {
int value = 1;
switch (value) {
case ONE: break;
case TWO: break;
}
}
}
While this enum switch is not:
import java.lang.annotation.RetentionPolicy;
public class Foo {
private final static RetentionPolicy RT = RetentionPolicy.RUNTIME;
private final static RetentionPolicy SRC = RetentionPolicy.SOURCE;
public static void main(String[] args) {
RetentionPolicy value = RetentionPolicy.RUNTIME;
switch (value) {
case RT: break;
case SRC: break;
}
}
}
I know that what goes in the case must be a constant, so why can I use a "final static int" as constant but not a "final static <your enum>"?
Because a case statement label must have either a compile time constant or an EnumConstantName. JLS 14.11
Compile time constants can only be strings and primitive types, as described by JLS 15.28. Thus you can not use a static final <your enum>, as it is neither a compile time constant, nor the name of an enum.
The case argument must be primitive; it cannot be an object.
However, you can use enums as follows:
RetentionPolicy value = ...
switch (value) {
case RUNTIME:
case SOURCE:
}
Because value is declared to be of type RetentionPolicy you can use the enum constants directly inside the switch.
Or simply use a if-elseif case :
private final static int ONE = 1;
private final static int TWO = 2;
public static void main(String[] args) {
int value = 1;
if(value.equals(ONE)){
}
else if(value.equals(ONE)){
}
}
The compiler says
unqualified enumeration constant name required
So your value of RT would need to be RUNTIME instead of RetentionPolicy.RUNTIME to make your code work. But of course that is not possible. Why not use the RetentionPolicy enum directly? If you want to stick to your final static declaration, you need to assign the whole enum to your final static variable.
I had a similar requirement and worked around this problem by switching on the Enums ordinal number instead of switching on the enum itself. This is not very beautiful/intuitive but it works:
public class Foo {
private final static int SRC = 0; // == RetentionPolicy.SOURCE.ordinal();
private final static int RT = 2; // == RetentionPolicy.RUNTIME.ordinal();
static{
if (RT != RetentionPolicy.RUNTIME.ordinal() || SRC != RetentionPolicy.SOURCE.ordinal()) {
throw new IllegalStateException("Incompatible RetentionPolicy.class file");
}
}
public static void main(String[] args) {
RetentionPolicy value = RetentionPolicy.RUNTIME;
switch (value.ordinal()) {
case RT: break;
case SRC: break;
}
}
}
Note that it is of course not possible to declare the constant as e.g.
private final static int SRC = RetentionPolicy.SOURCE.ordinal();
for the same reason one is not able to declare the constant as an Enum in the first place...