Java variable declaration - java

Ok, this might be basic, but I want good programmers' opinions on this.
What is a good way to handle variables in a small class file?
I like modularizing methods and keeping methods that do really specific things.
I end up passing variables between those methods. Is it a good practice to make variables used across many methods as member variables? Or is it better to pass the variables to methods?
For example:
class Test{
somefunction(int a, int b, int c, int d) {
doSomething(a, b, c);
doOneMoreThing(a, c, d);
}
void doSomething(int a, int b, int c) { }
void doOneMoreThing(int a, int c, int d) { }
}
In the above example, do you think the variables should be kept as member variables?
Please explain why one methodology is preferred over the other.

Do you need to keep the variables around between method calls, and reuse their value? If so, they should be class members. (At least in some class - not necessarily this one.)
Otherwise it is somewhat a matter of taste. One important factor is though that local variables don't add state to the object, which can be useful if it is used concurrently. Keeping all variables local may even allow you to make your class immutable, which usually makes it automatically thread-safe. But even in a single-threaded environment an immutable class is easier to understand and maintain.
OTOH passing lots of parameters around can be awkward. You may consider introducing a Parameter Object to alleviate this problem.

If I have some variables that I would end up passing to a bunch of private methods, I'll often move them into a private inner worker class.
Instead of
class Foo {
public doSomething(...) {
// some setup
doSomethingRecursively(a, b, c);
}
private void doSomethingRecursively(A a, B b, C c) {
if (baseCase) { ... }
doSomethingRecursively(a + 1, b, c);
}
}
I'll move the variables that never difference into properties on a worker.
class Foo {
public doSomething(...) {
// some setup
new AppropriatelyNamedHelper(b, c).doSomethingRecursively(a);
}
private static final class AppropriatelyNamedHelper {
final B b;
final C c;
AppropriatelyNamedHelper(B b, C c) {
this.b = b;
this.c = c;
}
void doSomethingRecursively(A a) {
if (baseCase) { ... }
doSomethingRecursively(a + 1);
}
}
}
This makes it clear to a reviewer what in each scope is invariant within that scope.

Member variables should exist to maintain some kind of state in a class. If your class maintains state then definitely define member variables for those things you need to track. If a class does not maintain state then there is no reason to make things members (I have had to debug legacy code where variables should not have been made members but were and it was causing errors when making multiple calls to the object because the state was unpredictable).
However, while you might like "modularizing" functionality, read up on coupling vs. cohesion. There is a balance to be struck between having too much functionality in a class but fewer dependencies and having very little but highly specific functionality and lots of dependencies.

Having useless member variables is usually regarded to as bad design.
But you can (and should) combine multiple variable sets into a new class if you use that variables in lots of methods.

If you don't care about the state of the object, then passing the variables to the method is fine. In that case, I would use a static modifier on the method, then you don't have to instansiate the class and you can call the method like so:
Test.doSomething(1, 2, 3);

Instance Variables: Their values are unique to each instance of a class. When an object is allocated in the heap, there is a slot in it for each instance variable value. Therefore an instance variable is created when an object is created and destroyed when the object is destroyed.
Class Variable: The Class variables are declared with a static keyword/modifier.There is only one copy of class variable no matter how many times the class is instantiated. They are stored in static memory.
Local variables: Only accessible within the method they are declared. When a method is entered, an area is pushed onto the call stack. This area contains slots for each local variable and parameter. When the method is called, the parameter slots are initialized to the parameter values. When the method exits, this area is popped off the stack and the memory becomes available for the next called method.
If you are going to reuse the variables, then you can declare them as class variables. If not, then they should be local variables defined in their respective methods.

First of all Somefunction(... } is a syntax error. Second, method names should start with lower case letters, and class names should start with upper case. Third, we have no idea what the best way is without knowing what these methods do, what they're used for, and where their parameters come from

Depends on how often you have to change your code (or you should think about how often you're going to change it when you design it). If the signature changes you have to change it in a lot of places. That means more code to test even when you refactor the signature. I would err on the side of creating member variables and encapsulating.

Related

Accessing local variables in the main method via reflection

Just having a play around with Java reflection and I think I'm getting the hang of it for the most part. I understand from this question/answer that, for the most part, I'm limited to static variables. If I have an instance of the class though, I can access non-static variables, which does make sense, I get that much.
Say I have the following two classes:
public class A
{
private static int _staticInt;
public static void main(String[] args)
{
B instanceOfB = new B();
}
}
public class B
{
private int _nonStaticInt;
public Game() {}
}
I understand how to access _staticInt, that's not an issue.
My understanding is that I can get the Field for _nonStaticInt in the same way (i.e. Field f = B.class.getDeclaredField("_nonStaticInt");). From other research (javadocs, trails, etc) I have gathered that I need an instance of B in order to get the value of _nonStaticInt.
So my question; Since main is static, is it possible to access instanceOfB in order to access the value of _nonStaticInt? I don't think it is possible, but I thought it's always best to consult people that are more knowledgable than myself before giving up on the idea.
Since main is static, is it possible to access instanceOfB in order to access the value of _nonStaticInt?
"No." Local variables (being in a static method or not) cannot be accessed with the Java Reflection API. Reflection only works at the type level, not the byte-code level2.
The stated understanding of the linked question is correct; reflection access of a non-static (instance) field logically requires an instance. That is, the issue then isn't about reflecting on the B type, the issue is about obtaining the B instance (which is assigned to a local variable) to reflect upon.
To do this the B instance has to be "bled" somehow - e.g. assigned to a static field or passed as an argument to a method/constructor from main1 - so that it can be used with reflection later as the object who's instance members are to be accessed.
The cleanest approach would probably be to pass the B instance down through the appropriate context (or "DI"), perhaps with the aide of IoC .. and maybe changing the type to avoid the use of reflection entirely.
1 Another possible way to "bleed" the B instance is to attach a debugger and inspect/use the local variable within the main methods executing frame - but this sounds like trying to swat a fly with a club.
2 Even tooling like BCEL/ASM wouldn't immediately help during the execution of the main method. Rather it would be used to deconstruct the method, add in the required hooks/code to "bleed" or use the instance created, and then construct a modified method to execute.
Yes, you can get the value of _nonStaticInt in that same way:
B instanceOfB = new B();
Field f = B.class.getDeclaredField("_nonStaticInt");
// Because the variable is private you need this:
f.setAccessible(true);
Object content = f.get(instanceOfB);
System.out.println(content);
The value will be 0, that is the default value for an int.

how can I change variables in super class

I want to write a program in java that consists of three classes, A, B, and C, such that B extends A and C extends B. Each class defines an instance variable (named "x").
how can I write a method in C to access and set A's version of x to a given value, without changing B or C's version?
I tried super.x but It wasn't true.
any help?
thanks for your attention in advance
You can access A's version of x like this:
((A)this).x
as long as x wasn't declared private in class A. I've just tested it.
Note that for fields, there is no overriding (as there is for methods). Thus, for an object of class C, there will be three x fields, but two of them can't be accessed normally because they are hidden by the other field named x. But casting the object as above will allow you to get at it, if it would have been visible if not hidden.
I think it is very poor practice to declare fields of the same name in a class and its subclasses. It's confusing. It can happen legitimately if, say, you have a class A and you later change the implementation of A and add a new private field z; in that case, it may not be possible to make sure no subclasses of A already have a field z, since you don't even always know what all the subclasses are (if A is a class you've distributed publicly, for instance). I think it's for that reason that Java allows you to have fields of the same name, and why the hiding rules are the way they are, because it allows things like this to work without breaking all the other subclasses. Other than that, though, I recommend not having fields of the same name in superclasses and subclasses. Perhaps if they're all private it might be OK, though.
Do the following
public static void main(String[] args) throws Exception {
C c = new C();
System.out.println("c:" + c.x);
System.out.println("a:" + ((A)c).x);
c.changeAX();
System.out.println("c:" + c.x);
System.out.println("a:" + ((A)c).x);
}
static class A {
int x;
}
static class B extends A {
int x;
}
static class C extends B {
int x;
public void changeAX() {
((A)this).x = 4;
}
}
Fields are resolved relative to the declared type of the reference. The above prints
c:0
a:0
c:0
a:4
The field will have to have at least protected visibility.
You don't want to be hiding class members, it's bad practice because it can easily confuse anyone trying to figure out which member you are referring to.
I misread your question. You can't do what you're trying to do.
Extending classes means adding information in several layers, ultimately resulting in one object. Although there are multiple layers, this doesn't mean that the layers are separate of eachother.
The variable X will be defined at one level (probably A) and after that the other classes will use this variable (if it's declared protected), but they won't have their own copy of it. You can only access your direct superclass.
This class might give you additional access to its own superclass, but you don't have direct contact with the super-super class.

assigning attribute values in constructor or class, which is better?

Is there any difference between the following types of instantiation?
Whether I set the value directly where the variable is defined, or in the class constructor.
If not, what is best practice?
"In class":
class A {
boolean b = true;
public A(){
}
}
"In constructor":
class B {
boolean b;
public B(){
b = true;
}
}
The variable type is just for the example.
The only difference I see is, when the attribute is a complex type (a class) which constructor depends on values that are given to the constructor of the containing class:
class A {
B b;
public A(String s){
b = new B(s);
}
}
Actually they both are equivalent. From a readability point of view, however, the first one is more readable. Also, it's easy to see the default value when someone navigates to the variable declaration from an IDE (like ctrl + mouse-click in Eclipse).
Check out what the official tutorial has to say -
This works well when the initialization value is available and the
initialization can be put on one line. However, this form of
initialization has limitations because of its simplicity. If
initialization requires some logic (for example, error handling or a
for loop to fill a complex array), simple assignment is inadequate.
Instance variables can be initialized in constructors, where error
handling or other logic can be used. To provide the same capability
for class variables, the Java programming language includes static
initialization blocks.
So you can easily use the simple one-liner initialization technique when the process is simple. For complex initialization choices, constructors are the way to go.
If you assign the value to variable in the class, then while creating instance of the class, directly your desired value will get assigned to the variable.
If you assign values in the constructor, then your variables will be first assigned a default value and then the values from constructors will get assigned.
Read on initialization blocks, constructors and their order of execution
In case of best practice,
If passing all the values to the costructor is must while creating the object, then construction initialization must be used.
If there are some values which need to be default for every object, then you can assign outside constructors.
Use an initialization block. Initializing Fields
public class X {
// The following is the initializer block
{
}
public X() {
}
}
Instance variables are assigned default values in case you don't assign one! Bu default boolean instance variables are assigned value false.
public class HelloWorld {
boolean b;
public void printData() {
System.out.println("Defualt boolean value is " + b);
}
public static void main(String args[]) {
HelloWorld hw = new HelloWorld();
hw.printData();
}
}
and the output is Defualt boolean value is false.
Where are you assigning your variable is purely a design choice.
Both are almost same.
But an effective line from docs
. Instance variables can be initialized in constructors, where error handling or other logic can be used.
Instance field initializations are copied to the start of the constructor by the compiler, so the first two approaches generate the exact same code (or pretty darn close).
(Note however that the above is not quite true for static field initializations vs the static initializer method.)
It's mainly a question of which seems clearer and less likely to lead to confusion/errors down the road. And that depends on numerous factors, including personal style.
I'd recommend C:
class C {
private boolean b = true;
}
-> no (explicit) constructor -> less code -> easier to read

Java Variables Conventions

I'm confused with variable declarations in Java code.
I read... don't try to use global variables declarations .
Don't use something like this:
package cls;
public class test {
private String var;
public someMethod(){ ... }
}
And use ?
package cls;
public class test {
public someMethod(){
String var = null;
}
}
I don't know which is the correct way....
It totally depends on what you need.
Your first example, however, isn't a global variable--it's an instance variable.
Variables should have as small a scope as possible. This makes code easier to reason about.
Instance variables are central to what OOP is all about--classes (objects) exist to encapsulate object state, and the methods that operate on that state. For example, a Person class would likely have first and last name instance variables:
public class Person {
private String firstName;
private String lastName;
// Plus getters and setters for each.
}
This allows instance methods to access the first and last name variables directly without having to pass them between all the methods that need them.
The second example is a local variable. It's visible only in the method it's declared in. A reference to it may be passed to other methods.
Both are correct. Neither of those are global variables. The first one is a class field. It's unique to each instance of the class that you make. Class fields (ie. variable) stay with the instance of the class until the class itself is deleted.
The second one is a method scope variable. It's only there for temporary purposes to perform the calculations needed for the method to work, and once the code in the method is done, the variable goes away.
You use each for different purposes. For example, if you're writing a Car class, you'd probably have a class field for SteeringWheel and Brake. But if you had a method to calculate the average miles per gallon, you might create a method scoped variable to help perform the calculation.
Java doesn't have global variables. The first variable is class level and maintains the state of class instances and hence exists as long as an instance of the class while the second is a method's local variable that exists only during method's execution. You can use the first variable to store state information that spans multiple method calls. The second variable disappears as soon as the control leaves the method. Also, every time you call the method another variable, accessible by the same local name is created on the stack.
You can't have truly "global" variables in Java the same way as you can in a language such as C. Java forces you to structure your program in an object oriented way.
In your example above, if var is required throughout a whole test object and is important to have stored, then you would use the first example. If var is only required in someMethod and it's not important for a test object to store it then use the second example.
Take note that even with the first example, var is encapsulated within a test object, so it's not really "global" at all, apart from maybe slightly to the member function of test (which is the whole point of instance/member variables).
The closest thing in Java to "global" data is something like:
public class GlobalVars {
public static int globalInt;
}
And you could access globalInt throughout your code as GlobalVars.globalInt, without creating an instance of GlobalVars.

Local variables in java

I went through local variables and class variables concept.
But I had stuck at a doubt
" Why is it so that we cannot declare local variables as static " ?
For e.g
Suppose we have a play( ) function :
void play( )
{
static int i=5;
System.out.println(i);
}
It gives me error in eclipse : Illegal modifier for parameter i;
I had this doubt because of the following concepts I have read :
Variables inside method : scope is local i.e within that method.
When variable is declared as static , it is present for the entire class i.e not to particular object.
Please could anyone help me out to clarify the concept.
Thanks.
Because the scope of the local variables is limited to the surrounding block. That's why they cannot be referred to (neither statically, nor non-statically), from other classes or methods.
Wikipedia says about static local variables (in C++ for example):
Static local variables are declared inside a function, just like automatic local variables. They have the same scope as normal local variables, differing only in "storage duration": whatever values the function puts into static local variables during one call will still be present when the function is called again.
That doesn't exist in Java. And in my opinion - for the better.
Java doesn't have static variables like C. Instead, since every method has a class (or instance of a class) associated with it, the persistent scoped variables are best stored at that level (e.g., as private or static private fields). The only real difference is that other methods in the same class can refer to them; since all those methods are constrained to a single file anyway, it's not a big problem in practice.
Static members (variables, functions, etc.) serve to allow callers of the class, whether they're within the class or outside of the class, to execute functions and utilize variables without referring to a specific instance of the class. Because of this, the concept of a "static local" doesn't make sense, as there would be no way for a caller outside of the function to refer to the variable (since it's local to that function).
There are some languages (VB.NET, for example), that have a concept of "static" local variables, though the term "static" is inconsistently used in this scenario; VB.NET static local variables are more like hidden instance variables, where subsequent calls on the same instance will have the previous value intact. For example
Public Class Foo
Public Sub Bar()
Static i As Integer
i = i + 1
Console.WriteLine(i)
End Sub
End Class
...
Dim f As New Foo()
Dim f2 as New Foo()
f.Bar() // Prints "1"
f.Bar() // Prints "2"
f2.Bar() // Prints "1"
So, as you can see, the keyword "static" is not used in the conventional OO meaning here, as it's still specific to a particular instance of Foo.
Because this behavior can be confusing (or, at the very least, unintuitive), other languages like Java and C# are less flexible when it comes to variable declarations. Depending on how you want it to behave, you should declare your variable either as an instance variable or a static/class variable:
If you'd like the variable to exist beyond the scope of the function but be particular to a single instance of the class (like VB.NET does), then create an instance variable:
public class Foo
{
private int bar;
public void Bar()
{
bar++;
System.out.println(bar);
}
}
If you want it to be accessible to all instances of the class (or even without an instance), make it static:
public class Foo
{
private static int bar;
public static void Bar()
{
bar++;
System.out.println(bar);
}
}
(Note that I made Bar() static in the last example, but there is no reason that it has to be.)

Categories