Because I believe it is a good programming practice, I make all my (local or instance) variables final if they are intended to be written only once.
However, I notice that when a variable assignment can throw an exception you cannot make said variable final:
final int x;
try {
x = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
x = 42; // Compiler error: The final local variable x may already have been assigned
}
Is there a way to do this without resorting to a temporary variable? (or is this not the right place for a final modifier?)
One way to do this is by introducing a (non-final) temporary variable, but you said you didn't want to do that.
Another way is to move both branches of the code into a function:
final int x = getValue();
private int getValue() {
try {
return Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
return 42;
}
}
Whether or not this is practical depends on the exact use case.
All in all, as long as x is a an appropriately-scoped local variable, the most practical general approach might be to leave it non-final.
If, on the other hand, x is a member variable, my advice would be to use a non-final temporary during initialization:
public class C {
private final int x;
public C() {
int x_val;
try {
x_val = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
x_val = 42;
}
this.x = x_val;
}
}
No it is not the right place, imagine you got more then 1 Statement in your try and catch block, the first one says : x = 42. After some others Statements the try block fails, and it goes to the catch block, where your Saying x = 30. Now you defined x twice.
Related
I have a class X that saves ints in an array:
public class X{
public int[] a;
public boolean[] allocated;
//constructor
public X(int len){
this.a = new a[len];
this.a = new allocated[len];
}
public void save(int tosave) throws ArrayStoreException{
int pos = 0;
for(int i=0; i<allocated.length; i++){
if(allocated[i] == true){
pos++;
}
}
if(pos == allocated.length){
throw new ArrayStoreExeption("no free space left");
}
a[pos] = tosave;
allocated[pos] = true;
}
}
And the class Y with save2 that I still need to implement...
public class Y extends X{
public void save2(int tosave){
// to be implemented
}
}
For save2 I want it to do the same as save with the exception, that if there is no more free space left or the ArrayStoreException occurs then I want the array to be doubled the size and then the parameter inserted to the array.
So if I do:
try{
super.save(tosave); // If no exception is thrown, does it save 'tosave'?
}catch(ArrayStoreExeption e){
System.out.println("noe free sapce left");
}
My first question is: if the try block does not trigger an exeption, will the code after catch block execute?
I don't know where to put the piece of code savely which doubles the array size if there is no more space left or the exeption is thrown.
Can someone help?
EDIT:
Can I place the code, that double the array inside the catch block?
the code you have posted has a number of syntax errors. I suggest you get those fixed and repost if this answer doesn't satisfy you.
yes you can implement your code to expand the array inside the catch block of the subclass. It will need to call the superclass's save method
your subclass should probably override the save method rather than create a new save2 method
using a boolean array doesn't make a lot of sense. Given you are not leaving any gaps wouldn't it be easier just to keep a single index of the first unallocated spot?
wherever possible keep your member variables private or protected. In this case if the subclass is going to expand the array then it will likely need to be protected. Better would be to make it private and have a protected method in the superclass to expand it.
Arrays.copyOf will do the expansion for you
So putting all that together:
class Fixed {
private int size;
private int[] store;
private int index = 0;
public Fixed(int size) {
this.size = size;
store = new int[size];
}
public void save(int value) throws ArrayStoreException {
if (index == size)
throw new ArrayStoreException();
store[index++] = value;
}
protected void expand() {
size *= 2;
store = Arrays.copyOf(store, size);
}
}
class Expandable extends Fixed {
public void save(int value) {
try {
super.save(value);
} catch (ArrayStoreException x) {
expand();
save(value);
}
}
}
If you prefer to avoid the recursion then you could use:
public void save(int value) {
try {
super.save(value);
} catch (ArrayStoreException x) {
expand();
try {
super.save(value);
} catch (ArrayStoreException x) {
throw new IllegalStateException("Cannot save after expansion");
}
}
}
You can put the code in finally block.
Regardless there is an exception or not, finally block do execute. (Exception : if called System.exit(0); in the try block.)
Conceptually, let's begin with
Try Block - You put the code here where you think there may be an ArrayStoreException.
Catch Block - This Block runs only if there is any exception thrown from try block.
You put the code, how it should handle. As per requirement, you can throw a message to console telling about the details of error, as in your case ArrayStoreException message and can prompt the user that you are going to double the capacity of ArrayList and can hence write the code for increasing the size of ArrayList
Finally Block - This block runs regardless of any exception is thrown or not. You can write the code for increasing the size of ArrayList here also. But, it will run even if there is no ArrayStoreException and the ArrayList has the capacity.
Note : If there is an exception thrown by the code, and is not handled or declared, so the code will stop running and no further code will run. But, if there is a proper handling of errors, the rest of the code runs.
For your case, I will suggest definitely to leverage the use of try-catch-finally block and put the code for doubling the size in catch block.
Basically, my goal is to be as efficient as possible by "deleting" variables when I'm done with them, even if still in scope. So far, I've been using if(true) to manually create a scope that defines the lifetime of variables, but I'm looking for something like, var.close(), a function that's only purpose is to cause a variable to essentially go out of scope and no longer have a memory location reserved for it.
The example I use below could obviously use for() to sidestep this particular instance(the assignment wants me not to use for()), but my concern is wider than variables used as indexes.
(ignore any other logic/syntax errors present, as I haven't proofread this yet)
package root;
import javax.swing.JOptionPane;
public class DebugEight4
{
public static void main(String[] args)
{
String array[] = new String[100];
String entry = " ";
final String STOP = "/']";
StringBuffer message = new StringBuffer(
"The words in reverse order are:\n"
);
if(true)
/*
*forces x out of scope
* after while statement ends
*/
{
int x = 0;
while(!entry.equals(STOP))
{
entry = JOptionPane.showInputDialog(null,
"Enter another word\n" +
"Enter " + STOP + " when you want to stop");
if(!entry.equals(STOP) && x != 100)//prevents fragmentation error
{
array[x] = entry;
}
else
{
JOptionPane.showMessageDialog(null, "That\'s all! Let's see the results.");
}
++x;
}
}/* end x scoping if
* If the if(true) wasn't here, x would still exist!
*/
for(int y = array.length-1; y > 0; --y)
{
message.append(array[y]);
message.append("\n");
}
JOptionPane.showMessageDialog(null, message);
}
}
Any thoughts?
This is exactly what scopes are for. You don't need to invent your own scoping system. Any variable should be declared in the smallest possible enclosing scope. But that's as far as you need to go with this. It is a visibility principle, not an efficiency principle, as all the stack needed for a method is allocated on entry to the method, and inner scopes don't correspond to bytecode instructions in any way.
To create a more-limited scope is easy enough. Just create a new block:
public static void whatever() {
int a = 5; // Exists until end of method
{
int b = 5; // Exists until end of outer block
{
int c = 5; // Exists until end of inner block
}
// c is no longer accessible
}
// b is no longer accessible
}
I'd recommend against this for a few reasons:
It's harder to read for little gain
The compiler or JIT can automatically figure out the lifetime of variables and automatically handle what you're attempting to do
You can't overlap variable lifetimes this way (nesting means that the most-nested variable must expire off the stack before less-nested ones)
Ok so in my cs class we have an assignment that requires us to return a value and then set it to zero. I can't figure out how to do this without using a secondary variable(which would break requirements) so I would appreciate some help. here are the exact requirements.
"Has a use() method that returns the value contained in the points field. It also resets the points field to zero. You’re going to have to think about the order of operations here to make this work correctly."
package Game;
import java.util.Random;
public class HealthPotion
{
private int points;
boolean Haspotion;
HealthPotion()
{
Random num1 = new Random();
int num = num1.nextInt(10)+1;
points=num*10;
}
public int Use()
{
return points;
}
public int getPoints()
{
return points;
}
}
That's not really possible without abusing a finally block, i.e.
try {
return points;
} finally {
points = 0;
}
However it's really hard to believe that would be what's wanted, since it's not a good idea to write code like that.
Include a setter method like this.
public void setValue(){
this.points=0;
}
Call this method after you get the value.
How about this?
public int Use()
{
int tmp = points;
points = 0;
return tmp;
}
It has limitations, especially if points can be changed by a different thread while this method executes. But if you are working in a single-threaded environment this should be ok.
This should work
int points = 5;
public void test(){
System.out.println(use() +" " + points);
}
private int use(){
return points - (points = 0);
}
returning 5 0
Because I believe it is a good programming practice, I make all my (local or instance) variables final if they are intended to be written only once.
However, I notice that when a variable assignment can throw an exception you cannot make said variable final:
final int x;
try {
x = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
x = 42; // Compiler error: The final local variable x may already have been assigned
}
Is there a way to do this without resorting to a temporary variable? (or is this not the right place for a final modifier?)
One way to do this is by introducing a (non-final) temporary variable, but you said you didn't want to do that.
Another way is to move both branches of the code into a function:
final int x = getValue();
private int getValue() {
try {
return Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
return 42;
}
}
Whether or not this is practical depends on the exact use case.
All in all, as long as x is a an appropriately-scoped local variable, the most practical general approach might be to leave it non-final.
If, on the other hand, x is a member variable, my advice would be to use a non-final temporary during initialization:
public class C {
private final int x;
public C() {
int x_val;
try {
x_val = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
x_val = 42;
}
this.x = x_val;
}
}
No it is not the right place, imagine you got more then 1 Statement in your try and catch block, the first one says : x = 42. After some others Statements the try block fails, and it goes to the catch block, where your Saying x = 30. Now you defined x twice.
Is it a good practice to use properties as local variable. In cases where there are many methods which uses some variables, In each method the variable value changes. This avoids many times creating new variables and the code increases. Any suggestion?
private void method1(){
int totalLength = length1 + 10;
int totalBreath = (breath1 + breath2) + 20;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method2(){
int totalLength = length1 + 20;
int totalBreath = (breath1 + breath2) + 30;
int size = (totalLength * totalLength);
System.out.println(size);
}
private void method3(){
int totalLength = length1 + 60;
int totalBreath = (breath1 + breath2) + 10;
int size = (totalLength * totalLength);
System.out.println(size);
}
As you can see, totalLength, totalBreath, size is repeated in every method. Can i make them as fields of the class? So, i need not declare it in every method.
private void method1(){
totalLength = length1 + 10;
totalBreath = (breath1 + breath2) + 20;
size = (totalLength * totalLength);
System.out.println(size);
}
I read your question as, "When should a local variable be promoted to be a field of the class?"
The best answer is "it depends" but then again, its accuracy is quickly eclipsed by its lack of usefullness.
Fields should have a relationship to the class itself, as in is the field an attribute of the class? I include an example below to illustrate the syntax difference, but I agree with this post that it should be avoided if it pollutes the meaning of the class.
Usually you only need to have a field when you need the value of the field to be maintained between calls to different methods for a given instance of the class, with the option of making it static when the value should be maintained between method calls for all instances of the class. It will depend on several factors like shop convensions, performance goals, existing codebase, etc. so there is no single right answer without specific code. This question seems to include similar points. If you find yourself using the approach below, you might consider other approaches like refactor the behavior into a help class.
Another question asks the same question but from the perspective of a programming student.
Examples:
public class VariableScope {
int field1 = 3;
void foo() {
int a = 2;
// variable passing in width
bar1(1);
bar2(1);
// variable passing in depth
bar3(a);
// uses a field to reduce variable passing
baz1();
baz2();
}
void bar1(int param) {
System.out.println("param=" + param);
}
void bar2(int param) {
System.out.println("param=" + param);
}
void bar3(int param)
{
System.out.println("Passing param to bar4");
bar4(param);
}
void bar4(int param){
System.out.println("param=" + param);
}
void baz1() {
System.out.print("field1=" + field1);
}
void baz2() {
System.out.print("field1=" + field1);
}
}
From what it sounds like, if you're using the variable for multiple methods you're should declare the variable as a global variable. But yes, If no other method needs that variable , and you don't want to be writing a bunch of return statements you can use local variables
I suppose you mean a field by property which usually has accessor and mutator (get,set-methods).
In common you should keep the scope of a variable as small as possible. An example if you use many for loops like:
for ( int i = 0 ; i < 10 ; i++ ) {
}
and replace this by
int i;
method1() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
method2() {
for ( i = 0 ; i < 10 ; i++ ) {
// some code;
}
}
If one thread calls method1() and another one method2() you would face a race condititon.
You can easily introduce hard to find bugs in your code.
I assume you mean something like this:
Class foo() {
int x;
public bar() {
for(x = 0; x <100; ++x) ...
} }
No, it's not good practice.
One place where it can even be harmful is in the synchronization/concurrency/multi-threaded case: if you are working with class members, they are going to need be synchronized which will eat into performance. Otherwise you risk multiple threads overwriting the value of the field and that can lead to errors in your program (likely hard to debug).