How to transform this class to immutable? - java

I am in process of learning immutability but I am not able to exactly digest how this works. So in order for me to understand immutability, I created a test program.
The funtion getArray(Box b) will make an ArrayList of Box objects.
Expected output: Actual output:
Output Output
a is 5 a is 5
b is 10 b is 10
Output Output
a is 0 a is 4
b is 0 b is 40
Output Output
a is 1 a is 4
b is 10 b is 40
Output Output
a is 2 a is 4
b is 20 b is 40
Output Output
a is 3 a is 4
b is 30 b is 40
Output Output
a is 4 a is 4
b is 40 b is 40
Logic:
public class Box {
static int a;
static int b;
public Box() {
a = 5;
b = 10;
}
public int getA() {
return a;
}
public void setA(int x) {
a = x;
}
public int getB() {
return b;
}
public void setB(int x) {
b = x;
}
public void display() {
System.out.println("Output");
System.out.println("a is " + a);
System.out.println("b is " + b);
System.out.println();
}
}
Main Class
import java.util.ArrayList;
public class Check {
public static void main(String[] args) {
Box b = new Box();
b.display();
ArrayList<Box> arr2 = new ArrayList<Box>();
arr2 = getArray(b);
for (int i = 0; i < arr2.size(); i++) {
arr2.get(i).display();
}
}
public static ArrayList<Box> getArray(Box b) {
ArrayList<Box> arr = new ArrayList<Box>();
for (int i = 0; i < 5; i++) {
b.setA(i);
b.setB(i * 10);
arr.add(b);
}
return arr;
}
}
How do I change the logic in such a way that I get the desired output? How do we decide how and where to edit the code to ensure immutability?

This would be an immutable:
public final class Box {
final int a;
final int b;
public Box(int a, int b) {
this.a = a;
this.b = b;
}
}
And then your array method would be:
public static ArrayList<Box> getArray(Box b) {
ArrayList<Box> arr = new ArrayList<Box> ();
for(int i =0 ;i <5; i++) {
arr.add(new Box(i, i*10));
}
return arr;
}
The data members are declared final because they're immutable, and so getters are pointless and setters just make no sense.
The class is declared final so you cannot subclass it.

In short, an immutable object is an object whose state cannot be modified after it's created. Your immutable Box object would look like this:
public final class Box {
private final int a;
private final int b;
public Box(int a, int b) {
this.a = a;
this.b = b;
}
public int getA() {
return a;
}
public int getB() {
return b;
}
public void display() {
System.out.println("Output");
System.out.println("a is " + a);
System.out.println("b is " + b);
System.out.println();
}
}
Notice that the variables a and b are assigned exactly once, during the construction of the Box instance. There are no setters, because Box's immutability means that its state (including variables a and b) will not change over its lifetime.
The final keyword in front of a and b means that you must assign them exactly once. It's actually considered good practice to make all your variables final unless you specifically need them not to be; but for an immutable object it's essential.
You were using the static keyword. Static has nothing to do with immutability. It means the variable is shared among all instances of the Box class. In my example, each Box instance has its own copies of a and b, because I didn't make them static.
To wrap this up, I'll give an example of your main class which has the desired output:
public class Check {
public static void main(String[] args) {
final List<Box> arr2 = getArray();
for (int i = 0; i < arr2.size(); i++) {
arr2.get(i).display();
}
}
public static ArrayList<Box> getArray() {
final ArrayList<Box> arr = new ArrayList<>();
for (int i = 0; i < 5; i++) {
final Box box = new Box(i, i * 10);
arr.add(box);
}
return arr;
}
}
Note that a new instance of box is created at every iteration of the loop.

Related

How do I solve Java '.class' expected error Java, compilation failed [duplicate]

This question already has an answer here:
What does "error: '.class' expected" mean and how do I fix it
(1 answer)
Closed 4 months ago.
I was trying to create a java program that adds 2 numbers but keep getting this error
error: '.class' expected
return int ad();
1 error
error: compilation failed
Here is my code
public class Sum {
int a;
int b;
int add;
public int ad(int a, int b){
int add = (int) a + b;
return add;
}
public static void main(String[] args) {
return int ad();
}
}
public class Sum {
/*
int a;
int b;
int add;
*/
public int ad(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int sum = ad(1, 3);
System.out.println(sum);
}
}
main()'s return type is void - it cannot return anything. Mostly it is used to call functions.
Pass parameters to ad() - or you will get a compile time exception - it is expecting 2 integers.
Redundant casting here: int add = (int) a + b; - for a simple method like this, you can directly return a + b;
Unused variables - all your member variables are unused.
Solution 2 (using member variables):
public class Sum {
private int a;
private int b;
private int ad() {
return a + b;
}
public static void main(String[] args) {
Sum s = new Sum();
s.a = 1;
s.b = 2;
int sum = s.ad();
System.out.println(sum);
}
}
There are some points in your code:
main() can't return anything because it's a void method.
You don't have to use member variables in this situation. Member variables are most used in classes. Like for instance when you want to create a Person class.
You don't have to type int add = (int) a + b because you don't have to convert anything.The datatype is already an int.
Here's an example of what you can do:
public class Main {
public int add(int a, int b){
int result = a + b;
return result;
}
public static void main(String[] args) {
Main main = new Main();
System.out.println(main.add(1, 1));
}
}
Output:
2
Hope this information was useful!
The method "public static void main(String[] args)" is static and the method "public public int ad(int a, int b)" is non-static.
If you want to reach the method "public int ad(int a, int b)" then make an instance of class Sum and call the method "ad(int a, int b)", or make the method "ad(int a, int b)" static. As already mentioned in comments above, "public static void main(String[] args)" has no return type - it is void, so no "return int ad()" in main method is needed.
Alrernative 1 - Make an instance of class Sum and call method ad(int a, int b):
public class Sum {
int a;
int b;
int add;
public int ad(int a, int b) {
int add = (int) a + b;
return add;
}
public static void main(String[] args) {
Sum sum = new Sum(); // Make an instance of class Sum
int result = sum.ad(1, 2); // and call method ad
System.out.println("Result: " + result); // Output: 'Result: 3'
}
}
Alternative 2 - Make method ad(int a, int b) static:
public class Sum {
public static int ad(int a, int b) { // Make method ad static
int add = (int) a + b;
return add;
}
public static void main(String[] args) {
int result = Sum.ad(1, 3); // Calling static method ad
System.out.println("Result: " + result); // Output: 'Result: 3'
}
}
Read more about diffrence between static and non-static methods here:
https://stackoverflow.com/questions/3903537/what-is-the-difference-between-a-static-method-and-a-non-static-method#:~:text=A%20static%20method%20belongs%20to%20the%20class%20and%20a%20non,class%20that%20it%20belongs%20to.&text=In%20the%20other%20case%2C%20a,class%20has%20already%20been%20instantiated.

Fill objects fields from Stream<Integer>

I have class
#Data
Test{
private int[] a;
private int[] b;
}
And I have private Stream<Integer> stream with 1 000 000 integers.
How can I make the following:
iterate over all integers in stream
create new Test
if i!=0 add i to test.a else add i to test.b
At last I need a Test object with 2 arrays where a contains all non-zero elements and b contains all zeroes.
I need 1 Test object.
Maybe you could use 2 stream operations and on 1 instance of the test use setters for a and b.
public class Foo {
public static void main(String[] args) throws IOException {
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(0);
myList.add(1);
Test t = new Test();
t.setA(myList.stream().filter(x -> x != 0).mapToInt(x -> x).toArray());
t.setB(myList.stream().filter(x -> x == 0).mapToInt(x -> x).toArray());
System.out.println("t: " + t);
}
}
class Test {
private int[] a;
private int[] b;
public void setA(int[] array) {
a = array;
}
public void setB(int[] array) {
b = array;
}
#Override
public String toString() {
return "Test {a=" + Arrays.toString(a) + ", b=" + Arrays.toString(b) + "}";
}
}
If you know beforehand that you have 1,000,000 integers, there is no need to collect zeros at all:
int[] a = stream.mapToInt(Integer::intValue).filter(i -> i!=0).toArray();
int[] b = new int[1_000_000 - a.length];
Test test = new Test(a, b);
Here is a sample implementation that splits the Stream into two Streams
public class Main {
static class Test {
private int[] a;
private int[] b;
Test(int[] a, int[] b) {
this.a = a;
this.b = b;
}
}
public static void main(String[] args) {
IntStream.Builder zeroStreamBuilder = IntStream.builder();
IntStream.Builder nonZeroStreamBuilder = IntStream.builder();
IntStream intStream = IntStream.of(0, 0, 1, 2, 3, 4);
intStream.forEach(value -> {
if (value == 0)
zeroStreamBuilder.add(value);
else
nonZeroStreamBuilder.add(value);
}
);
int[] a = zeroStreamBuilder.build().toArray();
int[] b = nonZeroStreamBuilder.build().toArray();
Test result = new Test(a, b);
}
}
If you are willing to use a List, then it will be possible skip building arrays from streams .build().toArray() as you can directly add the values to the resulting lists.

Multiple returns of different data types

I'm completely lost and getting desperate.
I'm working with Netbeans and what I'm trying to do is just have 2 or more variable of different types be sent to one class, be modified at that location, and then all be returned to the starting location along with the modifications they went under.
I can't put them into an array because in this instance I'm using an Integer and a Double and in the actual code I'm using a lot more than just 2 variables.
public class Passing_Objects {
public void main(String[] args) {
int a = 5;
double b = 10;
? = Extra.Carry(a, b);
System.out.println("A = " + a + ", B = " + b);
}
class Extra {
public int a;
public double b;
public Extra(int _a, double _b) {
this.a= _a;
this.b= _b;
return ?;
}
Either what I'm looking for can't be done or my feeble incompetent mind is too stupid to comprehend the solution everyone else is using.
Either way I can't make any progress in my code unless I solve this problem.
Could someone please help me understand what I need to do and would the solution be any different if variables A or B were arrays?
Something like this ?
public class Passing_Objects {
public void main(String[] args) {
int a = 5;
double b = 10;
Extra extra = new Extra(a, b);
System.out.println("A = " + extra.getA() + ", B = " + extra.getB());
}
class Extra {
public int a;
public double b;
public Extra(int a, double b) {
this.a= a;
this.b= b;
}
public int getA(){
return a;
}
public double getB(){
return b;
}
}
}
Edit :
To alter the values after a first initialization, you need setters.
Something like these two methods in your Extra class.
public void setA(int a){
this.a = a;
}
public void setB(double b){
this.b = b;
}
then in your Passing-Objects class, you can set new values by invoking the setter methods.
extra.setA(20);
extra.setB(20d);
Hope it helps.

trying to reassign value to class instance variables

I am being beginner trying to learn java basics and here in the this program I am confused why
we can't reassign the value of class instance variable.
this is error in this program. Please guys help me out to figure it out. thanks
class AddInsideClassVar{
int a = 3;
int c;
c = a + a;
public static void main(String args[]){
System.out.println();
}
}
You may define fields within a class, but you are not allowed to put calculation statements outside of a method definition. A field declaration is of the form type; or type = value;
For example (from your code);
class AddInsideClassVar{
static int a = 3; // ok this is a declaration for a field (variable)
static int c; // ok, this is too
//c = a + a; // this is a statement and not a declaration. A field may be
// declared only once
static int d = a + a; // this will work since it is part of a declaration.
public static void main(String args[]){
System.out.println("a=" + a + ", c=" + c + ", d=" + d);
}
}
You cannot execute c = a + a in that section. If anything you'd need to do
int a = 3;
int c = a + a;
If you make these variables static then you could do
private static int a = 3;
private static int c;
static {
c = a + a;
}
You can try this (just an example of workaround):
class AddInsideClassVar{
static {
int a = 3;
int c;
c = a + a;
System.out.println(c);
}
public static void main(String args[]){
}
}
You may be mixing your statics with instance variables. Here's how I would write this to not confuse myself:
public class AddInsideClassVar{
int a;
int c;
public void doStuff() {
a = 3;
c = a + a;
}
public static void main(String args[]){
AddInsideClassVar instance = new AddInsideClassVar();
instance.doStuff();
System.out.println(c);
}
}
a and c are instance variables. They are manipulated by a non-static method which requires an instance of the class to operate on. So, I create the instance in main(), then call the function to manipulate instance variables.
Explanation : int c = a + a is a declaration whereas " c = a + a ; " ( alone ) is a statement ; You have a point, it does not make much sense ;
class MyClass {
int a = 3;
int c = a + a; // Correct
}
or
class MyClass {
int a = 3;
int c;
public void addition () {
c = a + a; // Correct
}
}
but not
class MyClass {
int a = 3;
int c;
c = a + a; // Incorrect
}
NOTE : On the other, the Scala programming language ( compiles to JVM ) allows you to do the following :
scala> class MyClass { val a:Int = 3;
var c:Int = _;
c = a + a ; // Correct
}
defined class MyClass

Java - Using the output from one class in another

I'm trying to write a program that takes the output of adding two numbers in one class together and adds it to a different number. Here is the first class:
public class Add{
public static void main(String[] args) {
int a = 5;
int b = 5;
int c = a + b;
System.out.println(c);
}
}
And the second:
public class AddExtra{
public static void main(String[] args) {
Add a = new Add();
int b = 5;
int c = a.value+b;
System.out.println(c);
}
}
How do I get this to work? Thanks.
Suggestions:
You need to give the Add class a public add(...) method,
have this method accept an int parameter,
have it add a constant int to the int passed in,
and then have it return the sum.
If you want it to add two numbers, rather than a number and a constant, then give the method two int parameters, and add them together in the method.
Then create another class,
In this other class you can create an Add instance,
call the add(myInt) method,
and print the result returned.
You could try
public class Add{
public int c; // public variable
public Add() { // This is a constructor
// It will run every time you type "new Add()"
int a = 5;
int b = 5;
c = a + b;
}
}
Then, you can do this:
public class AddExtra{
public static void main(String[] args) {
Add a = new Add(); // Here, the constructor is run
int b = 5;
int c = a.c + b; // Access "a.c" because "c" is a public variable now
System.out.println(c);
}
}
Read more about constructors here.

Categories