I am trying to convert this data type to call out the method later on in another class to switch around layouts being made in other methods such as recipe1Layout(); by the index number of a class that has a field of a Class<?> Array.
Here is the getItem() method
public int getItem(){
int index = 0;
for(int i = 0; i < 100; i++) {
try{
index = recipe.getClass().getField("Classes").get(i);
} catch(Exception e){
}
}
return index;
}
Here is the Recipe Class
public class Recipes {
public Class<?>[] Classes = {
ChileConLecheActivity.class,
ArrozActivity.class,
EnchiladasActivity.class,
SopaActivity.class
};
}
The type of Class needs to be here because I have other uses for the recipe class.
For example, making a new instance of all classes to later on be called out to make adjustments to all the classes with one method.
The only thing I can think of is converting the type Class to an int so I can call out the method returning the index number I can do something like recipe.
index = Integer.parseInt(Classes[I].getName().toString());
But this is where I am asking for help I have no idea how to get rid of the error in the logcat.
The error shows up as
IndexOutOfArrayException
First off, stop using reflection. Use a public static array.
public class Recipes {
public static final Class<?>[] CLASSES = {
ChileConLecheActivity.class,
ArrozActivity.class,
EnchiladasActivity.class,
SopaActivity.class
};
}
Then, assuming your recipe instance has a field of what Class<Activity> it is assigned to, then, you would want something like this
public int getItem(){
int index = -1;
for(int i = 0 ; i < Recipe.CLASSES.length; i++) {
if (recipe.getActivityClass().equals(Recipe.CLASSES[i]) {
index = i;
break;
}
}
return index;
}
However, under certain situations, coupling one Activity class to any single Recipe instance, probably isn't a good idea.
I am trying to convert this data type to call out the method later on in another class to switch around layouts being made in other methods
if I understand what you are trying to do, you want a some mapping structure to some classes which have some pre-defined layouts.
Generally, this can be done with enums and OOP patterns
Have some base classes like this
public interface Layoutable {
int getLayout();
}
public enum Recipe {
ChileConLeche(R.layout.chile_con_leche),
Arroz(R.layout.arroz),
Enchiladas(R.layout.enchiladas),
Sopa(R.layout.sopa)
int layout;
Recipe(int layout) { this.layout = layout };
}
Ideally, you would want to use Fragments, but here is an example of an Activity structure
public abstract class RecipeActvity extends AppCompatActivity implements Layoutable {
protected Recipe recipe;
protected int getLayout() { return recipe.layout; }
}
public class ChileConLecheActivity extends RecipeActvity {
public ChileConLecheActivity() {
this.recipe = Recipe.ChileConLeche;
}
#Override
public void onCreate(...) {
setContentView(getLayout());
}
}
You can also combine this with a Map<Recipe, Class<RecipeActivity>>, from which you would use map.get(Recipe.ChileConCarne) to get the respective class element, for which you can startActivity() with
So I've read about the pass-by-value nature of Java and I've tried to change my variable after passing it to a function by having the function return the variable again. I didn't succeed in that.
My code
public class Logic {
private int position;
public class Logic(){
position = 1;
}
public void appendPosition(){
position = calculatePosition(position);
}
}
This is the barebones code. I call this method from an instance of Logic which is instantiated in another class:
public class MainLogic {
ILogic L;
public MainLogic(ILogic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
}
Through repeated debugging I find to my dismay that the position variable does not change at all. The position variable passed to calculatePosition changes fine, as expected. What am I missing? I've tried making the variable public and static.
calculatePosition
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations = new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations = new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
public class Logic {
private int position;
public Logic(){
position = 1;
}
//to get position.....................
public int getPosition(){
return this.position;
}
public void appendPosition(){
position = calculatePosition(position);
}
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations =
new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations =
new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
}
//next class
public class MainLogic {
Logic L;
public MainLogic(Logic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
public static void main(String[] args) {
Logic L = new Logic();
MainLogic ml = new MainLogic(L);
System.out.println(ml.L.getPosition());
ml.start();
System.out.println(ml.L.getPosition());
}
}
Let's read your code.
// There is a logic class.
public class Logic {
// So Logic has a position. it starts with zero.
private int position;
// Logic also has an inner class, also called Logic.
public class Logic(){
position = 1;
// When a new Logic().Logic() is created, the instance
// variable of the parent instance gets set to one. WHAT?!?
}
// ... lots of code
}
So, It's a bit like that Yo Dawg! meme - I heard you like Logic, so we've put A logic instance into your Logic instance so you can Logic while your Logic.
You probably want a constructor.
// So this is Logic.
public class Logic {
private int position;
// When an Logic instance is created, position starts with 1.
public Logic(){
this.position = 1;
}
Ok. So we're not talking about Yo Dawg Memes.
So Let's talk pass by value.
Pass-by-value means classes are like very egotistic children: You can't play with their toys, unless they tell you so.
This is a good thingĀ® since this means only the owning instance is allowed to change their private state. Trust me, it prevents quite a bit of havoc.
One way to allow the outside world to actually change the state is by using query and mutator methods. Back in the day, we used to call them getter and setter, but that sounds too simple, so software architects will usually use the fancier term.
But... all of this doesn't really apply since calculatePosition() is defined at Logic. Oops.
Let's try this:
Renaming some instance variables
Be a bit verbose to help the debugger. baby steps.
(Also, dropping a few jokes to fish for upvotes).
public class Logic {
private int position = 1;
public void appendPosition(){
// When debugging strange stuff,
// keep each step simple.
// Is calculatePosition working as it should?
int newPosition = calculatePosition(this.position);
this.position = newPosition;
}
// Always use parameters as final. It's good karma.
// You don't NEED to declare them as final,
// but let's try to be EXTRA clear.
private int calculatePosition(final int targetPosition){
// Yes, make as much as you can immutable
// You'll save a ton of mental bandwidth.
final int localCopy = targetPosition +6;
if(snakeLocations[localCopy]>0) {
return (localCopy -6);
// Don't force the maintenance programmer to
// read all your stuff. Return often, return early.
// This isn't Cc++, where you need to
// actually free your reference/pointers,
// so there's no point enforcing a single return.
}
if(ladderLocations[localCopy]>0) {
return (localCopy+6);
}
return localCopy;
}
}
So... Did this worked as it should?
I found the answer. This is often my mistake in posting here. I try to strip down my code as much as possible to ease the work for you guys, but sometimes the problem lies outside of the scope of what I provide due to a lack of understanding, or oversight, on my part.
I was actually calling MainLogic from two levels above:
public mainFrame() {
initComponents();
logic = Factory.getMainLogic();
}
where
public static class Factory {
public MainLogic getMainLogic(){
PlayerLogic pL = new PlayerLogic();
ImageLogic iL = new ImageLogic();
DieLogic dL = new DieLogic();
MainLogic mainLogic = new MainLogic(pL,iL,dL);
return mainLogic;
}
}
I forgot I had accidentally put Factory as static. My sincerest apologies for wasting your time.
I'm still a relative newbie when it comes to Java, coming mainly from a C# background.
I was discussing the lack of 'out' parameters in Java methods with a colleague and how to work around this. He suggested creating a structure/class to hold the various parameters and passing it back.
Sometimes this feels 'wrong' to me - especially if I have a special method that I want to use to return a subset of parameters from a larger class.
So I wondered about using anonymous inline classes instead to achieve this. Code sample below.
Is this a sensible approach? Just wondering what the perceived wisdom is on this.
public class MyClass {
Patient myPatient = null;
// An interface to enable us to return these variables in a single call
public interface VitalStatsResponse { public void returnStats(int bloodPressure, int heartRate); }
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Lots of other variables here
public void calculateVitalStats(VitalStatsResponse response)
{
response.returnStats((bloodPressure * 2), (heartRate / 10) ;
}
}
public void doWork()
{
// We want the patient's blood pressure and heart rate returned by a single method call, so use an anonymous inline class
myPatient.calculateVitalStats(new VitalStatsResponse() {
#Override
public void returnStats(int bloodPressure, int heartRate) {
// Handle returned variables here
}
});
}
}
I would go for the simple solution of creating a VitalStats object. If you need the VitalStatus of a patient, then VitalStats is a concept in your application that can be represented as an Object.
public class VitalStatus {
final int bloodPressure;
final int heartRate;
public VitalStats(int bloodPressure, int heartRate) {
this.bloodPressure = bloodPressure;
this.heartRate = heartRate;
}
}
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Other variables
public VitalStatus getVitalStatus() {
return new VitalStats(bloodPressured * 2, heartRate / 2);
}
}
Out params is a procedural solution for return times. Java primarily fits the Object Oriented paradigm of programming and as such don't be afraid to make objects. This fits with the S in SOLID if your class is doing a lot of complex things see if you can break it down into smaller more manageable pieces.
I would also use "class to hold the parameters" over "inline anonymous inner class"
public class MyClass implements VitalStatsResponse{
Patient myPatient = null;
private ArrayList<VitalStatsResponse> response;
void MyClass(ArrayList<VitalStatsResponse> response) {
this.response = response;
}
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Lots of other variables here
public void calculateVitalStats()
{
for(int i = 0; i < response.length; i++) {
// call returnStats method of every registered callback
response.get(i).returnStats((bloodPressure * 2), (heartRate / 10) ;
}
}
}
// any client can register/unregister callback via these methods
void registerResponse(VitalStatsResponse response) {
this.response.add(response);
}
void unRegisterResponse(VitalStatsResponse response) {
this.response.remove(response);
}
public void doWork()
{
// We want the patient's blood pressure and heart rate returned by a single method call, so use an anonymous inline class
myPatient.calculateVitalStats();
}
public void returnStats(int bloodPressure, int heartRate) {
// implement the body according to this class requirement
}
}
I am sorry if this question was asked before, but I need a good suggestion to solve next design problem:
Task: given that we have a base service that operates with data of given set of types, we need to design support of extensions for that service that has extended type set.
Bad Solution:
class BaseServiceType {
public static final int TYPE_A = 0;
public static final int TYPE_B = 1;
public static final int LAST_USED_BASE_TYPE_INDEX = TYPE_B;
}
And its extension
class ExtendedServiceType extends BaseServiceType {
public static final int TYPE_E = LAST_USED_BASE_TYPE_INDEX + 1;
public static final int TYPE_F = LAST_USED_BASE_TYPE_INDEX + 2;
}
My task is fairly simple that has only one extension. I am not trying to solve more general problem with multiple independent extensions.
I have a feeling that enum would work here, but no idea if it feasible.
One solution is to build the ids dynamically. Class initilization is thread safe so you can do this.
class BaseServiceType {
protected static int id = 0;
public static final int TYPE_A = id++;
public static final int TYPE_B = id++;
}
And its extension
class ExtendedServiceType extends BaseServiceType {
public static final int TYPE_E = id++;
public static final int TYPE_F = id++;
}
class AlsoExtendedServiceType extends BaseServiceType {
public static final int TYPE_X = id++;
public static final int TYPE_Y = id++;
}
The only problem is the order classes are initialized change the ids. If this matters, you need to access the classes in the order you need.
I have a value that I want to pass between 2 classes, but I get the following error:
Syntax error on token ";", , expected when initializing called value
from another class
Class where I have the initial value
public class Game extends Activity implements OnClickListener{
RandomMathQuestionGenerator question = new RandomMathQuestionGenerator();
private static final String TAG= "Sudoku";
public static final String KEY_DIFFICULTY =
"org.example.sudoku.difficulty";
public static final int DIFFICULTY_NOVICE = 1;
public static final int DIFFICULTY_EASY = 2;
public static final int DIFFICULTY_MEDIUM = 3;
public static final int DIFFICULTY_GURU = 4;
public int value = 0;
private GameView gameView;
public Game()
{
if (KEY_DIFFICULTY == String.valueOf(1))
{
value = 2;
}
else if (KEY_DIFFICULTY == String.valueOf(2))
{
value = 3;
}
else if (KEY_DIFFICULTY == String.valueOf(3))
{
value = 4;
}
else if (KEY_DIFFICULTY == String.valueOf(4))
{
value = 6;
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
}
#Override
public void onClick(View v)
{
//code here
}
}
Class where I call the value
public class RandomMathQuestionGenerator {
Game num = new Game();
int number = 0;
number = num.Game(value);
//public int number = 0;
//number = num.Game(number);
private static final int NUMBER_OF_QUESTIONS = 1;
private static final int MIN_QUESTION_ELEMENTS = 2;
private final int MAX_QUESTION_ELEMENTS = number;
private static final int MIN_QUESTION_ELEMENT_VALUE = 1;
private static final int MAX_QUESTION_ELEMENT_VALUE = 100;
private final Random randomGenerator = new Random();
//rest of irrelevant code below
}
The syntax error is irrelevant in the long run.
In Android your must start an Activity with an Intent. (See this Developer's Guide article.) When you want to start Game use:
Intent intent = new Intent(this, Game.class);
startActivity(intent);
Also you declare KEY_DIFFICULTY as final (unchangeable):
public static final String KEY_DIFFICULTY = "org.example.sudoku.difficulty";
So your if-else block will never be true in any of these cases:
if (KEY_DIFFICULTY == String.valueOf(1))
And to compare Strings in Java you must use equals(), == will give inaccurate results. (How do I compare strings in Java?)
If you want to pass the level of difficulty from one Activity to another use the Intent's extras, a public class variable, or another approach found in: How do I pass data between Activities in Android application?
Addition
You just added more code to your question and you have circular logic.
- When you create RandomMathQuestionGenerator object, you will create a Game object
- When you create Game object, you will create a RandomMathQuestionGenerator object
- When you create RandomMathQuestionGenerator object, you will create a Game object
- When you create Game object, you will create a RandomMathQuestionGenerator object
- When you create RandomMathQuestionGenerator object, you will create a Game object
- When you create Game object, you will create a RandomMathQuestionGenerator object
- When you create RandomMathQuestionGenerator object, you will create a Game object
- When you create Game object, you will create a RandomMathQuestionGenerator object
- ...
This will only stop when your app throws a StackOverflowException.
number = num.Game(value);
I don't see a method Game(int value) in your Game class. You need to create this method in your class:
public int Game(int value){
//code
}
I am also not sure you can name a method the same name as your class. I assume the fact it has a return value in the signature, it would be valid, but it would be bad practice to have a method name the same as your class anyway.
Case - In <init>
Here's my modified proposed code for RandomMathQuestionGenerator:
public class RandomMathQuestionGenerator {
private Game num;
private int number;
public RandomMathQuestionGenerator() {
num = new Game();
number = num.value;
// Existing code here
}
// Existing code here
}
Case - In method code
Game num = new Game();
int number = num.value;
Here's what's wrong:
public Game - public is a field modifier, not a variable modifier, and is invalid in the middle of method code. Note that final is a valid modifier - it means that re-assigning the variable is a compile error.
Creating number with a placeholder value, then assigning to it - that 0 will never be used
num does not have a method Game, and value is not defined in this code. value is a property of Game objects, of which num is one. I strongly recommend renaming this variable - maybe gameInst would work.
Summary
(in progress)