Referencing a constructor without resetting parameter values? - java

Just for reference, I've taken like one high school class on Java, so this question should be super easy to respond to. I'm just having trouble figuring out a way to call a class method, the constructor, as a new object without putting in new values for the parameters. The constructor looks like this:
public Skills(int courage, int intelligence, int stamina, int crafting,
int blacksmithery, int herbalism, int slingSkill,
int bowSkill, int swordSkill, int armor, int stealth, int
lifeForceSkill){
this.courage = courage;
this.intelligence = intelligence;
this.stamina = stamina;
this.crafting = crafting;
this.blacksmithery = blacksmithery;
this.herbalism = herbalism;
this.slingSkill = slingSkill;
this.bowSkill = bowSkill;
this.swordSkill = swordSkill;
this.armor = armor;
this.stealth = stealth;
this.lifeForceSkill = lifeForceSkill;
}
And when I establish it it my main method I do this:
Skills skills = new Skills(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
To set all the levels to 1 and then I have the object skills to work with later. (Am I getting the terms constructors and objects mixed up? If it's wrong just switch them all in your mind I think I'm being consistent with it at least).
The problem is I have a toString() method in the Skills class that I want to call in a separate method in the main class.
else if (optionChoice.equalsIgnoreCase("View Skills")){
Skills skills = new Skills();
System.out.println(skills.toString());
break;
}
Of course the object I create here throws an error because I cannot just write Skills(); without putting in all twelve values for the parameter. So how do I call the method from the Skills class when I can't create an object for it? It's imperative to functionality that the values do not change, and since they are variable and change with the program, I can't put any value in for them.
I know it's probably a super basic question but that's the level I'm at so any super basic answers would be helpful. Shouldn't take too much of your time. Thanks in advance!

Why not just make your skills object a static field instead of creating it within the main method?
public class WhateverYourClassIsCalled {
static Skills skills = new Skills(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
public static void main(String[] args) {
// ...
}
void yourOtherMethod() {
// ...
else if (optionChoice.equalsIgnoreCase("View Skills")) {
System.out.println(skills.toString());
break;
}
}
}

Related

Looping and sorting ojbects in a class [duplicate]

This question already has an answer here:
Java Sorting Date field
(1 answer)
Closed 4 years ago.
This is a noob question, sorry, but I am totally confused.
I had created a class called CalendarItems.
The fields are:
int index
String description
String textdate
int daysaway
The constructor uses the first three fields. And for the moment I have created four objects within the class.
I now want to do two things:
Loop through the CalendarItem's
For each CalendarItem calculate daysaway, which is the difference between the text date and today. I have figured out how to calculate this and can manually add do it by calling my method for item1, then for item2, etc
But i'd like to understand how i can do this with a loop. If i was in javascript i'd have an multi-dimensional array and could easy create a loop to cycle through it, but in the scary new world of java I am lost
Sort my CalendarItems on the daysaway field
I want to do this so that I can display them as CardViews in order of soonest-first.
[Inflating CardViews has proved blissfully straight-forward, and I can (again, with a manual 'loop') inflate a card for each CalendarItem and add the various fields to it. And creating the class and fields and adding my 4 sample objects has also worked, so it hasn't been a total lost weekend.]
I think where I am going wrong is that I keep thinking in terms of multi-dimensional arrays from my experience with javascript and Excel VBA, and however much I read about objects and iterator interfaces and arraylists in java, my brain is just refusing to take it in.
I have Google'd a lot on this, but every 'simple guide to iterators' has left me more confused than when I started.
Thanks in advance to anyone patient enough to help me.
I post my solution, as I already wrote it, it should be a complete one:
public class CalendarItem implements Comparable<CalendarItem> {
private int index;
private String description;
private ZonedDateTime textdate;
private long daysAway = 0;
public CalendarItem(int index, String description, ZonedDateTime textdate) {
this.index = index;
this.description = description;
this.textdate = textdate;
this.calculateDaysAway();
}
private void calculateDaysAway() {
this.daysAway = ChronoUnit.DAYS.between(textdate, ZonedDateTime.now(ZoneId.systemDefault()));
}
public long getDaysAway() {
return daysAway;
}
#Override
public int compareTo(CalendarItem o) {
if (this.daysAway < o.daysAway) {
return -1;
} else if (this.daysAway > o.daysAway) {
return 1;
} else {
return 0;
}
}
public static void main(String[] args) {
CalendarItem c1 =
new CalendarItem(0, "One", ZonedDateTime.of(2018, 5, 21, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c2 =
new CalendarItem(0, "Two", ZonedDateTime.of(2018, 5, 4, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c3 =
new CalendarItem(0, "Three",ZonedDateTime.of(2018, 5, 11, 0, 0, 0, 0, ZoneId.systemDefault()));
CalendarItem c4 =
new CalendarItem(0, "Four", ZonedDateTime.of(2018, 5, 1, 0, 0, 0, 0, ZoneId.systemDefault()));
List<CalendarItem> calendarItems = new ArrayList<>(Arrays.asList(c1, c2, c3, c4));
Collections.sort(calendarItems);
for (CalendarItem item : calendarItems) {
System.out.println("Item " + item.getDescription() + " is " + item.getDaysAway() + " days away.");
}
}
}
Note: I am using ZonedDateTime from java 8 to represent the date.
For 1) you can either create array in java or you can use ArrayList and store your objects in that arraylist and iterate over arraylist.
ArrayList<CalendarItem> list = new ArrayList();
list.add(obj1); // obj1 is the instance you created for the calendar item.
for(CalendarItem c: list){
// this is loop , do whatever you want here
}
For sorting, Either write a comparator class or implement comparable interface to your CalenderItem and override method compareTo. In this method you can provide comparison logic based on requirede field.
For (1), what have you tried? If you need a multi-dimensional array, nothing stops you from using one. Consider:
int dim1 = 5;
int dim2 = 10; // whatever you need
CalendarItem[][] items = new CalendarItem[dim1][dim2];
Im this case you would iterate your array the same way as with JavaScript.
for (int i = 0; i < dim1; i++) {
for (int j = 0; j < dim2; j++) {
// do whatever you need to do
}
}
You can also read about the enhanced for loop if you don't actually need a numerical index.
For (2) have a look at the Comparator interface in the javadocs as well as the methods in the Collections class, in particolar the sort method.

Instantiating from a class that has an array parameter in constructor in java

I have looked at several posts to reach an answer, but none came close enough.
I have a Q that might sound very empirical, and I am sure the answer is staring me in the face, but I am blinkered, I suppose! I have a class named DrugExcretion with a constructor that has a parameter that is a reference to an array (named drugExcretionCode).
I can't seem to work out the SYNTAX to instantiate (i.e. create an object) in my main class named DrugExcretionApp. Both classes are below:-
If anyone can direct me to a simple way to do this, it would be much appreciated. Thanks in advance.
public class DrugExcretion implements CautionInterface{
int[] drugExcretionCode;
private String[] drug;
public DrugExcretion(String[] drug){
this.drug = drug;
}
public String determineDanger(int[] drugExcretionCode){
String site1 = "kidney";
String site2 = "liver";
String site;
if (drugExcretionCode = 1){
return "reduce dosage in elderly";
}
else{
return "reduce dosage in children";
}
}
}
x ----------------- o ----------------- x ----------------- o
public class drugExcretionApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
final String drug1 = "enalapril";
final String drug2 = "captopril";
final String drug3 = "metoprolol";
final String drug4 = "amlodipine";
final String drug5 = "candesartan";
String drug[] = {drug1, drug2, drug3, drug4, drug5};
DrugExcretion listOne = new DrugExcretion(drug);
DrugExcretion.determineDanger(new int[]{1, 1, 2, 2, 1});
}
}
I get an error "DrugExcretion cannot be resolved to a type" which initially made me think that the project setup was incorrect so the DrugExcretion class could not be seen by the app class - I rearranged the classes to keep them in the same package, but the error persists.
It appears to be a problem with access modifiers - have I made something static inadvertently???
BTW, the interface simply contains a signature of the only method in the first class.
You have to call determineDanger like this:
listOne.determineDanger(new int[]{1, 1, 2, 2, 1]);
DrugExcretion.xxx would be for a static method xxx of DrugExcretion.
But determineDanger is an instance method, so needs to be invoked on an instance of the class, in this case listOne.
Since you are instantiating the DrugExcretion class, you need to call
listOne.determineDanger(new int[] { 1, 1, 2, 2, 1 });
Also, please check your code in the DrugExcretion class. It should be equals operator and not assignment.
if (drugExcretionCode == 1){

Why is my DataPoints method being called multiple times?

This test class:
#RunWith(Theories.class)
public class TheoriesConfusion
{
#DataPoints
public static int[] ints()
{
System.out.println("Generator called");
return new int[]{1, 2, 3, 4, 5};
}
#Theory
public void twoArgTest(int x, int y)
{
assertTrue(x < y || x >= y);
}
}
Prints the following output:
Generator called
Generator called
Generator called
Generator called
Generator called
Generator called
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.137 sec
This is quite counterintuitive, as I expect the data-generating function to be called only once. This has implications when creating random data, or any case where the data-generating method returns different results on each call, so I'd like to understand it.
After some experimentation, I've found that testing an array of length n against a Theory with c args, the generate function is called x times, where x = n^c + n^(c-1) + ... + n^0.
The source is a little difficult to comprehend, but my assumption is that it works something like this (pseudocode):
for firstArg in generateArgs():
for secondArg in generateArgs():
for thirdArg in generateArgs():
testTheory(firstArg, secondArg, thirdArg)
Which makes some sense, basically it's just not caching the results of the method, so if you want the method to be called just once, you have to annotate a static field, like:
#DataPoints
public static int[] ints = ints();
public static int[] ints()
{
System.out.println("Generator called");
return new int[]{1, 2, 3, 4, 5};
}

Modularly stubbing consecutive method calls with Mockito

I am trying to use Mockito to mock a "Reader" type class. Think of a data stream reader, it has methods to read various data types and advance the internal pointer after each read.
public interface Reader {
int readInt();
short readShort();
}
The class being tested reads in various data structures from the data stream. For example,
public class Somethings {
public List<Something> somethings;
public Somethings(Reader reader) {
somethings = new List<Something>();
int count = reader.readInt();
for (int i=0; i<count; i++) {
somethings.add(readSomething(reader));
}
}
private Something readSomething(Reader reader) {
int a = reader.readInt();
short b = reader.readShort();
int c = reader.readInt();
return new Something(a, b, c);
}
}
And finally, I have my test:
public class SomethingsTest {
#Test
public void testSomethings() {
Reader reader = Mockito.mock(Reader.class);
readCount(reader, 2);
readSomething(reader, 1, 2, 3);
readSomething(reader, 4, 5, 6);
Somethings somethings = new Somethings(reader);
Assert.assertEqual(2, somethings.size());
Assert.assertEquals(new Something(1, 2, 3), somethings.somethings.get(0));
Assert.assertEquals(new Something(4, 5, 6), somethings.somethings.get(1));
}
private void readCount(Reader reader, int count) {
when(reader.readInt()).thenReturn(count);
}
private void readSomething(Reader reader, int a, short b, int c) {
when(reader.readInt()).thenReturn(a);
when(reader.readShort()).thenReturn(b);
when(reader.readInt()).thenReturn(c);
}
}
Unfortunately, this does not work. reader.readInt() always returns 6 for every invocation. And I understand why it returns 6. That is not my question.
There are two options I can think of to fix the tests, but I don't particularly like either one.
The first option would be something like:
public class SomethingsTest {
#Test
public void testSomethings() {
Reader reader = Mockito.mock(Reader.class);
when(reader.readInt())
.thenReturn(2)
.thenReturn(1)
.thenReturn(3)
.thenReturn(4)
.thenReturn(6);
when(reader.readShort())
.thenReturn(2)
.thenReturn(5);
Somethings somethings = new Somethings(reader);
Assert.assertEqual(2, somethings.size());
Assert.assertEquals(new Something(1, 2, 3), somethings.somethings.get(0));
Assert.assertEquals(new Something(4, 5, 6), somethings.somethings.get(1));
}
}
This should work, but it's very monolithic and messy. It's difficult to see which return is for which piece of which structure, because they're all intermixed, with no structure.
The second option I can think of is something like:
public class SomethingsTest {
#Test
public void testSomethings() {
Reader reader = Mockito.mock(Reader.class);
NewOngoingStubbing readIntStub = when(reader.readInt());
NewOngoingStubbing readShortStub = when(reader.readShort());
readCount(readIntStub, 2);
readSomething(readIntStub, readShortStub, 1, 2, 3);
readSomething(readIntStub, readShortStub, 4, 5, 6);
Somethings somethings = new Somethings(reader);
Assert.assertEqual(2, somethings.size());
Assert.assertEquals(new Something(1, 2, 3), somethings.somethings.get(0));
Assert.assertEquals(new Something(4, 5, 6), somethings.somethings.get(1));
}
private void readCount(NewOngoingStubbing readIntStub, int count) {
readIntStub.thenReturn(count);
}
private void readSomething(NewOngoingStubbing readIntStub,
NewOngoingStubbing readShortStub, int a, short b, int c) {
readIntStub.thenReturn(a);
readShortStub.thenReturn(b);
readIntStub.thenReturn(c);
}
}
This at least maintains the structure of the original, but having to pass a separate object for each method call you want to make on the stubbed object is... ugh.
What would be the cleanest way to perform this test? Is there some option I'm missing here? Some functionality that I can leverage? I just started using Mockito tonight.. so I could very well be missing something.
Mockito does ongoing stubbing natively. Your first example is fine, but this should also work:
when(reader.readInt()).thenReturn(2, 1, 3, 4, 6);
The documentation for it is here.
If you have something handling particularly complex interaction, it's OK to roll out your own stub class. You may find that initialising some fake with realistic data, then using that, provides a clearer example of how the classes collaborate than Mockito can. If that's the case, go with clarity over convention. Mockito is IMO the best mocking framework out there, but sometimes I still roll my own.
When the standard methods for Mockito don't provide a mechanism to simulate your behavior, you can resort to implementing your own Answer. This is more work but provides extra flexibility.
Depending on your precise requirements, you could for instance create an Answer that returns a new element from a list of numbers, regardless of the request type (int or short). The variable readList can be a member that you can access from all the functions you use to set up your results.
final List<Integer> readList = new ArrayList<>();
// ... Fill readList with answers
Answer answerFromList = new Answer() {
Object answer(InvocationOnMock invocation) {
// Remove and return first element
return readList.remove(0);
}
}
when(reader.readInt()).thenAnswer(answerFromList);
when(reader.readShort()).thenAnswer(answerFromList);
Note that this Answer is a lot like the provided ReturnElementsOf, so you could use that directly as well.
You may create a class to deal with it, e.g.
private static class ReaderStubber {
private final Reader reader = Mockito.mock(Reader.class);
private final NewOngoingStubbing readIntStub = when(reader.readInt());;
private final NewOngoingStubbing readShortStub = when(reader.readShort());;
public Reader getReader() {
return reader;
}
private void readCount(int count) {
readIntStub.thenReturn(count);
}
private void readSomething(int a, short b, int c) {
readIntStub.thenReturn(a);
readShortStub.thenReturn(b);
readIntStub.thenReturn(c);
}
}
But then the question is, do you really need to do this with Mockito? Not everything should be mocked. Maybe just implementing a stub Reader for the test with some List<Integer> inside is better.
(Edit)
Also, if this is possible, maybe you should redesign the Reader to make it immutable and return some NewOngoingReading. Frequently (but not always) things that are hard to test are better to redesign. Also, you will not need to deal with synchronization.

Stack Overflow error when constructing a new object in Java

I'm trying to construct a PackingCase object with a certain set of values. While the program shows no errors during coding, when running, I get this error;
Exception in thread "main" java.lang.StackOverflowError
at assignment.pkg2.PackingCase.<init>(PackingCase.java:59)
at assignment.pkg2.PackingCase.<init>(PackingCase.java:60)
My code is as follows;
public class PackingCase {
// private fields go here
int serialNumber;
int timesUsed;
int timeCreated;
int timeStored;
String name;
String description;
void setCase(int s, int TU, int TC, int TS){
serialNumber = s;
timesUsed = TU;
timeCreated = TC;
timeStored = TS;
}
double volume(){
return serialNumber*timesUsed*timeCreated*timeStored;
}
public PackingCase(){
PackingCase PC1 = new PackingCase();
double vol;
PC1.setCase(1, 2, 3, 4);
vol = PC1.volume();
System.out.println(""+vol);
}
Line 59 is "public PackingCase(){" , and Line 60 is "PackingCase PC1 = new PackingCase();". I have no idea what's going on, considering that an example I found uses virtually the same code structure, and compiles with no errors whatever. Any help would be appreciated.
Each creation of a new object leads to the creation of another new object (and so on...) until the stack is overflowed.
Instead, it should be look like that:
public PackingCase(){
this.setCase(1, 2, 3, 4);
vol = this.volume();
System.out.println(""+vol);
}
You have a recursive call in the constructor. Leave the constructor empty (simply delete it) and run this code from main method:
public static void main(String[] a){
PackingCase pc1 = new PackingCase();
pc1.setCase(1, 2, 3, 4);
double vol = pc1.volume();
System.out.println(""+vol);
}
public PackingCase(){ PackingCase PC1 = new PackingCase(); ...}
Constructor recursively calls itself, causing stackoverflow.
You are calling new within the handler for new, creating an infinite loop (and since the stack is finite, it eventually runs out of space). But public PackingCase() { ... } is a constructor. That means it is only called when someone has already used new PackingCase(). The code within the constructor doesn't have to create the object (allocate space), just initialize it (set values for its fields).

Categories