Java: Modifying variables without arguments - java

I'm just beginning to learn Java and I have been very frustrated about learning Java's scope rules. You see I wish to create a Method without the use of arguments/parameters.
In JavaScript, I can do this with ease using functions:
/** Function to increase 2 vars.
/** **/
function modifyNow(){
a++;
b++;
} // END
var a = 5;
var b = 10;
modifyNow();
// By this part, a and b would be 6 and 11, respectively.
Now this is saving me a lot time and simple since whenever the function is called, var a and b, already exist.
So, is there a way to do this in Java without having arguments like how I do it in JavaScript? Or is there another way around this?
Thank you, appreciate the help... ^^

What is the problem with having a and b as private variables in your class, and increment them in modifyNow()? And by the way everything in Java must be in a class. You can't have global code mangling around...

You can do this for class fields, not for local variables.
class Clazz {
int a = 5;
int b = 10;
public void modifyNow() {
a++;
b++;
}
}
// ...
Clazz c = new Clazz();
c.modifyNow();
Now, after each call to modifyNow, the fields are updated.

Global variables are bad. Without knowing your intent, I would say you need to add the variables as members to your class. They are accessible then from any member function.

You see I wish to create a Method without the use of
arguments/parameters.
The best answer is: don't!
If you nevertheless want this, look for public static variables.

class Foo {
int a = 5;
int b = 10;
public void modifyNow(){
a++;
b++;
}
}

You need to use what are called member variables, they are tied to an instance of your class.
public class MyClass
{
// these are Class variables, they are tied to the Class
// and shared by all instances of the class.
// They are referenced like MyClass.X
// By convention all static variables are all UPPER_CASE
private static int X;
private static int Y
// these are instance variables that are tied to
// instances of the class
private int a;
private int b;
/** this the default no arg constructor */
public MyClass() { this.a = 5; this.b = 10; }
/** this is a Constructor that lets you set the starting values
for each instance */
public MyClass(final int a, final int b) { this.a = a; this.b = b; }
public modifyNow() { this.a++; this.b++; }
/** this is an accessor to retrieve the value of a */
public int getA() { return this.a; }
public int getB() { return this.b; }
}
final MyClass myInstanceA = new MyClass();
myInstance.modifyNow();
// a = 6, b = 11
final MyClass myInstanceB = new MyClass(1, 2);
myInstance.modifyNow();
// a = 2, b = 3
Everytime you do a new MyClass() you will get a new independent instance of MyClass that is different from every other instance.
As you are learning JavaScript is not related to Java in anyway. It is a terrible travesty that they picked that name for marketing reasons.

Related

Replace one field with another in a method

I'm trying to dynamically replace in a method body a field reference by another field reference. is that possible with bytebuddy?
The class I like to transform is like this:
public class TestReplace {
#replace
int a = 1;
int b = 2;
public int printA() {
return a;
}
public int printB() {
return b;
}
}
The transformation consists in replacing the variables marked with #replace in the methods that visit them. The replacement will be done by variables that I will insert.
The class already transformed should look like this:
public class TestReplace {
#replace
int a = 1;
int ___a = a * 10; // var inserted
int b = 2;
public int printA() {
return ___a;
}
public int printB() {
return b;
}
}
I am new to the subject and would appreciate any help you could give me.
Thanks in advance
Yes, this is possible using MemberSubstitution:
MemberSubstitution.relaxed()
.field(ElementMatchers.named("a"))
.onRead()
.doReplaceWith(otherField)
You can, for example, apply this transformation from a Java agent that you define using the AgentBuilder API. You probably also need to define the alternative field from this agent. You can reference this field using a FieldDescription.Latent.

(Java) Pass a parameter from a constructor to all the methods of a class

Say I have two methods in class 1. Can I pass a parameter to class 1 constructor which would then pass the parameter to both of the methods? Something like the example code below:
class stuff{
int c;
stuff(x){
c = x;
}
public static int sum(int a, int b){
stuff self = new stuff();
return c*(a + b);
}
public static int mult(int a, int b){
return c*(a*b);
}
}
class test{
public static void main(String args[]){
stuff foo = new stuff(5);
System.out.println(stuff.sum(1, 2));
System.out.println(stuff.mult(1, 2));
}
}
So from class test I want to access both methods from class stuff, while passing the parameters for the methods, but I also want to pass a global class parameter (5 in this case). How can I do this?
First two important things :
Constructors are designed to create instances.
Class names should start with an uppercase.
As you write :
class Stuff{
int c;
Stuff(x){
c = x;
}
...
}
Here you assign x to a c field.
But sum() and mult() are static methods.
They cannot use the c field.
Make these methods instances methods and you could use c in these methods.
public static void main(String args[]){
Stuff foo = new Stuff(5);
System.out.println(foo.sum(1, 2));
System.out.println(foo.mult(1, 2));
}
And use the current instance in these instance methods to sum or multiply current value with passed parameter values :
public int sum(int a, int b){
return c*(a + b);
}
public int mult(int a, int b){
return c*(a*b);
}
Just remove 'static' keyword from your methods, and do not create new instance of 'stuff' in a sum method. Instead just create instance of stuff in test#main method like you do right now, and it will work like you wanted.

Class scope variabile visibility

If I have:
class A
{
void foo()
{
int a = count;
}
void bar()
{
int a = c; // here ERROR
int c = 10;
}
private int count = 10;
}
here in foo count is used without problem also if it's declared after the use.
The same is not true in method bar where the variable c must be declared before its
use.
Which are the class scope rules? How they differs from method scope rules?
P.S.
My doubt is because the common scope resolutions rules:
When the compiler find count it should try to find it "back" to its
use but back there is Class A... so maybe private int count is "hoisting" at
beginning of Class A?
Imagine that you were a compiler, and you get to the line:
int a = c;
Won't you get angry and ask yourself "What is c"? The order is important1.
1count doesn't make a problem because it's a class member, it's known in the whole class. You can place class members in the beginning of the class, or at the end.
count is declared in the class while c is declared in the method
While compiling, the class would find count in the class.
class A
{
void foo()
{
int a = count;
}
private int count = 10;
}
is equal to put count anywhere in the class, as it is a class member and can be found in the class everywhere.
while in your case of
class A
{
void bar()
{
int a = c; // here ERROR
int c = 10;
}
}
c is not defined before use, as c is a local variable in a method.

Instantiation and declaration separate

My question is regarding the declaration and value assignment rules in Java.
When writing the fields we can declare and assign values together but we cannot do the same separately.
E.G.:
class TestClass1 {
private int a = 1;
private int b ;
b= 1;
private int sum;
public int getA() {
return a;
}
public int getB() {
return b;
}
public int getSum() {
sum = a + b;
return sum;
}
}
public class TestClass {
public static void main(String[] args) {
TestClass1 testClass1 = new TestClass1();
System.out.println("total =" + testClass1.getSum());
}
}
Here in line:
private int a = 1;
We are able to declare a as a private int and assign a value 1 to it. But in case of:
private int b ;
b= 1;
Eclipse does not allow this to happen and throws an error. Kindly explain the logic behind this.
Code inside a class, but outside a function, is purely declarations. It does not get "executed". It simply declares what fields a class contains.
The reason you can do the shorthand private int a = 1; is just syntactic sugar that the Java language allows. In reality, what happens is that the a = 1 part is executed as part of the constructor. It's just easier to read and write when it is next to the variable declaration.
It's something nice that the Java langage creators allowed. Not every language allows that, look at C++ as an example that does not always allow it.
you have to put b=1; inside a method or put this inside a constructor.
you are getting this error since you can't do any thing other than declaration(private int a= 1;
) in class level.
It's just a question of syntax in Java. In the example you show, you try to affect a value to b in the member declaration part of your class. This is not allowed by the syntax of Java. You can only do it when you declare your attribute, in the body of a method or in a static block if your attribute is static e.g. :
private static int b;
static {
b = 1;
}
It is only a syntax problem. You can do it like this :
private int b ;
{ // <- Initialization block
b= 1;
}
See What is an initialization block?
You are unable to write logic directly in the class. You should move it to the constructor.
Java only allow declaration within the class and outside any method. Declarations like int b = 1; will be executed when you initialize a new Object.

How to return multiple values from a function.

This is more of a logical question than code specific, I have some twenty functions, each function calculates two values of my interest. However I can only return one value from a function. Now the other option I have is to make a class and implement setter and getter with global variables. I want to know if this is a feasible and recommended way? Or there is a better way to do this?
Don't use global variables! Use some class that has your data as private fileds, and provide getters for it. Like in
class Pair<A,B> {
final A one;
final B two;
public Pair(A fst, B snd) { one = fst; two = snd; }
public A getFst() { return one; }
public B getSnd() { return two; }
}
Then you can elsewhere say something like:
return new Pair(42, "a result");
Return a Collection from your function containing your values of interest.
Depends on the problem. But 2 solutions are :
Make new class which instances will be returned by all this functions. This class would have 2 attributes for each needed answer.
Return array or Collection with this 2 answers.
You have to return a List or a array.
But if return types are different you can create custom class and use it as return type.
Example
public class Result {
private String name;
private int age;
// getters and setters;
}
Now you can have some thing like following
public static Result getInfo(){
Result result=new Result();
result.setName("name");
result.setAge(10);
return result;//now you can have String and int values return from the method
}
There are many ways: collections, arrays ...
In my opinion the only way is to define a class with these values.
you do not need getter and setter methods if you don't need to regulate the visibility of the contents
class MyReturnValue {
public int a;
public int b;
}
in your code:
...
MyReturnValue result=new MyReturnValue();
result.a=5;
result.b=6;
return result;
It is better to make a class and implement setter and getter with global variables rather than to Return Collection further it depends on your use.
You can do this
long[] function() {
long[] ret = { a, b };
return ret;
}
or
long[] a = { 0 }, b = { 0 };
void function(long[] a, long[] b) {
a[0] = ...
b[0] = ...
or add properties to an object.
private long a,b;
void function() {
a = ...
b = ...
}
in the last case you can value.
class Results {
public final long a;
public final Date b; // note: Date is not immutable.
// add constructor
}
public Results function() {
long a = ...
Date b = ...
return new Results(a, b);
}
I think making a Record class is the most suitable.
public class Record {
public final int a;
public final int b;
public Record(final int a, final int b) {
this.a = a;
this.b = b;
}
}
Then your functions can return type Record, and you can access it with let's say record.a and record.b.
This is also one of the few cases where public variables and no getters and setters can be justified.
UPDATE: Implemented a proposed change, now everything is final, which means that Record cannot be modified when you get it back, which seems to be in line with expectations. You only want the results and use those.
What about adopting varargs with generic helper function for getting around of number of returning variable limitation: In this solution, we won't have to declare a new class every time when number of returning variable changes.
class Results
{
private final Object[] returnedObj;
public Results(Object... returnedObj)
{
this.returnedObj = returnedObj;
}
public <E> E getResult(int index)
{
return (E)returnedObj[index];
}
}
Test case:
public static Results Test()
{
return new Results(12, "ABCD EFG", 12.45);
// or return larger number of value
}
//// And then returning the result
Results result = Test();
String x = result.<String>getResult(1);
System.out.println(x); // prints "ABCD EFG"
You could even return the values separated by a special character say a "~" if you are sure that the "~" won't appear in your results.

Categories