Initialize final variable within constructor in another method - java

I have a problem which isn't really that big, but still gives me some thought as to how Java constructors and methods are used.
I have a constant representing a radius I declare final, and also make it public for everyone to see. I don't want my code littered with getRadius() methods when I'm never ever going to change the radius.
I want to initialize the constant within the constructor as I want to apply certain criteria before assigning the radius, certain conditions have to be met. However, these conditions do take up some space, and I'd like to put them in some other method, to make the constructor cleaner.
The whole thing would initially look like this
public MyProblematicClass {
public final int radius;
public MyProblematicClass(... variables ...) {
if(... long criteria ...) {
radius = n;
}
}
}
and I'd love it to end up like
public MyProblematicClass {
public final int radius;
public MyProblematicClass(... variables ...) {
this.setRadiuswithCriteria(criteria);
}
private void setRadiuswithCriteria(criteria crit) {
if(... crit ...) {
radius = n;
}
I understand that I could potentially use the method for other purposes and that's the reason for giving me a 'blank field RADIUS may not have been initialized, so I'd like to know if there is a way to add a method which will only be used in constructors, for cleanliness's sake.

How about (using small caps for radius, because it is not a constant, as pointed out in the comments):
public MyProblematicClass(... variables ...) {
radius = getRadiusWithCriteria(criteria);
}
private int getRadiusWithCriteria(criteria crit) {
if(... crit ...) {
return n;
} else {
return 0;
}
}

You cannot assign to final variable outside constructor. As you said, method:
setRadiuswithCriteria(criteria crit) {
if(... crit ...) {
RADIUS = n;
}
Can be used outside constructor.
And you must set final variable to some value in constructor, not just after checking some criteria (always, not sometimes).
However, you might move the code outside the constructor, using the returned value of some function. Example:
class MyClass {
private final double i;
public MyClass() {
i = someCalculation();
}
private double someCalculation() {
return Math.random();
}
}

How about doing like this?
public MyProblematicClass {
public final int RADIUS;
public MyProblematicClass(... variables ...) {
RADIUS = this.setRadiuswithCriteria(criteria);
}
private int setRadiuswithCriteria(criteria crit) {
if(... crit ...) {
return n;
}
return 0;
}

Related

How do you return the total value of two methods that each take in a value?

My teacher wanted us to create program to compute the bills of our home. In java we were just going over objects and classes so I made
class Bills{
Bills... etc
The problem I am having is I dont know how to get a total of two methods that take in a value.
public double getWifepay(double x){
return x;
}
public double getHusbandpay(double y){
return y;
}
public double getTotalmoney(){
???
}
Your methods should probably just return some value that is stored within the object. So you would have something like:
public double getWifePay(){
return wifePay;
}
public double getHusbandPay(){
return husbandPay;
}
And
public double getTotalmoney(){
return getWifePay() + getHusbandPay();
}
and then you probably would want to write some setter methods like:
public void setWifePay(double wifePay) {
this.wifePay = wifePay;
}
public void setHusbandPay(double husbandPay) {
this.husbandPay = husbandPay;
}
And in your class definition you should have declared these fields:
public class Bills {
double wifePay;
double husbandPay;
// And then the methods from above
}
Create the previous two method (getwifepay, gethusbandpay) as static and call them in getTotalmoney function with class name. suppose class name is A so call as A.getwifePay(value)
Not sure I understand your model classes, but as you mention, for the "getTotalMoney" method to return the sum, the elements (the numbers in this case) should be given as parameters.
On the other hand, your "getWifepay" and "getHusbandpay" methods don't make much sense, as they are returning the same parameter which is given.
With all of this, you would need to have the method "getTotalmoney" call the other two and then make the sum, like this:
public double getWifepay(){
return x;
}
public double getHusbandpay(){
return y;
}
public double getTotalmoney(){
getWifepay() + getHusbandpay();
}
Finally, I suppose that these methods are within a given class (you mentioned Bill), making it maybe something like this:
class Bill {
private double x;
private double y;
private double getWifepay(){
return x;
}
private double getHusbandpay(){
return y;
}
public double getTotalmoney(){
getWifepay() + getHusbandpay();
}
}
Hope that solves your problem.

Java - changing a variable through pass-by-value

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.

Should I use an anonymous inner class to simulate 'out' parameters in Java?

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
}
}

How can I share instantiated objects between methods?

I have:
public class HFSim extends ApplicationTemplate
{
private static class AppFrame extends ApplicationTemplate.AppFrame
{
void setBuoy()
{
//code
Position buoypos=Position.fromDegrees(buoylat, buoylon);
}
void setVehicle()
{
//code
Position vehiclepos=Position.fromDegrees(lat, lon, elev);
}
double findDistance()
{
//find distance between marker (vehicle) and a buoy
Earth earth= new Earth();
double radius = earth.getEquatorialRadius();
double distancebetween=LatLon.ellipsoidalDistance(buoypos, vehiclepos, radius, 6356752.3);
return distancebetween;
}
How can I use the objects buoypos and vehiclepos in the setBuoy and setVehicle methods in the findDistance() method?
You have two clearcut options here:
Make buoypos and vehiclepos instance variables, or..
Provide more descriptive names for setVehicle() and give it a Position return type.
Option 1 would look like this:
...classname...
{
private Position vehiclePosition;
private Position bouyPosition;
public void setVehiclePosition()
{
this.vehiclePosition = ....
}
}
Option 2 would look like this:
...classname...
{
public Position createVehiclePosition()
{
vehiclePosition = ....
return vehiclePosition.
}
}
Finally, you would use them as either:
...classname...
{
public double findDistance()
{
...this.vehiclePosition...
or
Position vehiclePos = this.createVehiclePosition();
}
}
The option you choose is highly dependent on how the class is supposed to behave.
Use variables with the class scope. This essentially means
///outside of a method but within the class you'll want to set:
private this.bouypos = new Position;
private this vehiclepos = new Position;
//method1 {
Position this.buoypos=Position.fromDegrees(buoylat, buoylon);
//method2 {
Position this.vehiclepos=Position.fromDegrees(lat, lon, elev);
//method3 calls things set in method1 & 2
findDistance(){
//code
double distancebetween=LatLon.ellipsoidalDistance(this.buoypos, this.vehiclepos, radius, 6356752.3);
}
Make the findDistance method take two Positions as parameters
double findDistance(Position buoypos, Position vehiclepos){
}

Syntax error, telling me it wants ; and several other things

Just trying to run through some code for an assignment I'm doing. It is probably simple but for the life of me I can't figure out why I get the above error at the first line
(public WaterLog.......).
Later I want to pass it this line:
[ log = new WaterLog(8, damCapacity); ]
Any help would be appreciated, I am new to this sorry.
public class WaterLog(Integer windowSize, Integer maxEntry) {
private Integer size = windowSize;
private Integer max = maxEntry;
private ArrayList theLog(int windowSize);
private int counter = 0;
public void addEntry(Integer newEntry) throws SimulationException {
theLog.add(0, newEntry);
counter++;
}
public Integer getEntry(Integer index) throws SimulationException {
If (thelog.isEmpty() || thelog.size() < index) {
return null;
}
return thelog.get(index);
}
public Integer variation() throws SimulationException {
int old, recent = 0;
recent = thelog.get(0);
old = thelog.get(thelog.size-1);
return recent-old;
}
public Integer numEntries() {
return counter;
}
}
Assuming SimulationException is defined correctly:
class WaterLog{
private Integer size;
private Integer max ;
private ArrayList<Integer> theLog; //parameterize your lists
private int counter = 0;
public WaterLog(Integer windowSize, Integer maxEntry) //this is the behavior you were looking for
{
this.size = windowSize;
this.max = maxEntry;
theLog = new ArrayList<Integer>(windowSize);
}
public void addEntry(Integer newEntry) throws SimulationException {
theLog.add(0, newEntry);
counter++;
}
public Integer getEntry(Integer index) throws SimulationException {
if (theLog.isEmpty() || theLog.size() < index) { //Java is case sensitive
return null;
}
return theLog.get(index);
}
public Integer variation() throws SimulationException {
int old, recent = 0;
recent = theLog.get(0);
old = theLog.get(theLog.size()-1); //again, watch case, also size is a method
return recent-old;
}
public Integer numEntries() {
return counter;
}
}
See the comments I added.
EDIT: To explain a bit further what was going on, let's take a look at what you were doing.
public class WaterLog(Integer windowSize, Integer maxEntry) {
private Integer size = windowSize;
private Integer max = maxEntry;
private ArrayList theLog(int windowSize);
private int counter = 0;
You seem to have confused a class with a constructor. The variables you defined were attributes, which was correct. You needed to use the syntax I showed in my answer to create a constructor. For that same reason, you don't have access to variables like windowSize. To remedy this, we allow them to still be defined outside the constructor, but assigned values inside it, where we have access to windowSize and maxEntry.
If you want to pass some parameters to this class you need a constructor. By default Each and EVERY class comes with a default constructor - which is there, you just don't see it ( but can declare it). What you can then do is make an overloaded construcotr ( which takes some arguments ) and this is what you want so..
if you have a class
class WaterLog {
// no constructor
}
the above is really a
class WaterLog {
public WaterLog() {
// this is the constructor - if you do not declare it its still here, you just dont see it. Ofcourse you have option to declare it.
}
}
The overloaded constructor is something like this
class WaterLog {
public WaterLog() {
//default constructor
}
public WaterLog(Integer int, String string, etc...) {
//overloaded constructor
}
}
and the above is what you need in order to pass arguments to this class constructor. I am not briliant at explaining things but if you need more clarification just let me know :)

Categories