Interesting issue about java and linking "&" - java

I know that there isn't way to access to the links of variables in java (like in &C or &php). But for example I have such task:
public class JustTest {
private int n = 1;
private int x = 10;
public int[] getIntegers() {
return new int[] { n, x };
}
public void filledInteger() {
int[] vals = getIntegers();
System.out.println("Before change");
System.out.println(Arrays.toString(vals));
vals[0] = 2;
vals[1] = 20;
System.out.println("After change");
System.out.println(Arrays.toString(vals));
System.out.println("Values of name & xml");
System.out.println(n);
System.out.println(x);
System.out.println("calling getIntegers");
System.out.println(Arrays.toString(getIntegers()));
}
public static void main(String[] args) {
JustTest t = new JustTest();
t.filledInteger();
}
}
The result is:
Before change
[1, 10]
After change
[2, 20]
Values of name & xml
1
10
calling getIntegers
[1, 10]
So, I want to change values of "n" and "x" fields of the class instance. I can't do this by setting straightly (this->n = 20;), because I may dont know what fields do I have. Only method getIntegers knows.
(No in this code, but for example I have child class with its own fields and in the parent class I have a method filledInteger() which should change specified properties of the child class ( he knows about this properties from the method getIntegers which is abstract in the parent class and implemented in the child class))
Here is simple implementation (without inheritance), using links in php
<?php
class JustTest {
private $n = 1;
private $x = 10;
public function getIntegers() {
return array( &$this->n, &$this->x );
}
public function filledInteger() {
$vals = $this->getIntegers();
echo("Before change" . "<br/>");
echo(print_r($vals, true) . "<br/>");
$vals[0] = 2;
$vals[1] = 20;
echo("After change" . "<br/>");
echo(print_r($vals, true) . "<br/>");
echo("Values of n & x". "<br/>");
echo $this->n , "<br/>";
echo $this->x , "<br/>";
echo("call getIntegers again" . "<br/>");
echo(print_r($this->getIntegers(), true) . "<br/>");
}
}
$t = new JustTest();
$t->filledInteger();
?>
The result is:
Before change
Array ( [0] => 1 [1] => 10 )
After change
Array ( [0] => 2 [1] => 20 )
Values of n & x
2
20
call getIntegers again
Array ( [0] => 2 [1] => 20 )
That is what I exactly need. Im just curious how do I implement this in java
Hope you understood.
Next example:
public abstract class ParentTest {
abstract int[] getIntegers();
public void fillIntegers(int[] newIntegers) {
int[] integersOfChild = getIntegers();
for (int i = 0; i < integersOfChild.length; i++) {
integersOfChild[i] = newIntegers[i];
}
}
}
public class ChildTest extends ParentTest {
private int x;
private int y;
#Override
int[] getIntegers() {
return new int[] {x, y};
}
}
public class UseTest {
void main() {
List<ParentTest> list;
for (ParentTest item : list) {
item.fillIntegers(myItegers);
}
}
}
This is what I need. I have a list of ParentTest instances (it may be ChildTest, or ChildTest2, or ChildTest3; but they all children of a ParentTest) and I need to fill all fields with my integer values, but I dont know if items in the list instances of a ChildTest, or ChildTest2, or ChildTest3 class

How do I implement this in Java?
With great pain via the Reflection API. If you want to write code like this, the best idea is to use another language.
Consider programming in Groovy instead. You can use array syntax to directly access class members by name: t["n"] = 2; This works with legacy Java code, so there is no need to modify TestClass to support this usage.

The concept you are talking about is called pass by reference. Java has for the most part abandoned it - it creates too many side-effects, like the one you are seeing here.
The issue is that while unfortunately you can't do this here, it actually prevents a huge number of unintentional bugs being released.

What about something like that:
public final class JustTest {
private final Map<String, Object> fields;
public void filledInteger() {
System.out.println("Before change\n" + this.fields);
fields.put("N", 2);
fields.put("X", 20);
System.out.println("After change\n" + this.fields);
System.out.println("Values of name & xml\n" + fields.get("N")
+ "\n" + fields.get("X"));
}
private JustTest() {
this.fields = Maps.newHashMap(); // guava
fields.put("N", 1);
fields.put("X", 10);
}
public static void main(String[] args) {
final JustTest t = new JustTest();
t.filledInteger();
}
}

You can't do individual fields without reflection, but you can change the contents of collections. Note that this is not really intended behavior, but rather something you have to be careful of when using collections.
This outputs 5 3 2 4 2 4
public class Test
{
public Vector<Integer> args = new Vector<Integer>();
public void fillArgs()
{
args.add(5);
args.add(3);
}
public Vector<Integer> getArgs()
{
return args;
}
public static void main(String args[])
{
Test s = new Test();
s.fillArgs();
Vector<Integer> temp = s.getArgs();
for (Integer i : temp)
System.out.println(i);
temp.setElementAt(2, 0);
temp.setElementAt(4, 1);
for (Integer i : temp)
System.out.println(i);
for (Integer i : s.getArgs())
System.out.println(i);
}
}

Your php example does not return an array of ints, but rather an array of int pointers. This is NOT something you can do in Java, in fact, this is NOT something you want to do in Java. Give a use case, and there is likely a better way to solve the problem you have.
If you want to return an object that others can affect and that are contained as member variables, do that. An ArrayList, HashMap, etc... there are plenty of things that can fit your needs. If you are given someone elses class and you must stick your nose in their code, you can get around their private declaration doing the following:
public void setN(JustTest j, int n) {
//You would handle some exceptions here also
Field f = JustTest.class.getDeclaredField("n");
f.setInt(j, n);
}

Related

Generic Supplier for n Getters Across Collection

I have a collection of Java objects where I want to run a single function across multiple values I might find in some of the object's member variables. I'm looking for a nice way to pass in which getter should be used so I can have one method do all that work. I was thinking about something like a Supplier, but that would mean I have to have one per instance of the class. Here's an example of what I'm trying to do (only I would like to do this without the if statement or with potentially n getters a switch statement:
import java.util.ArrayList;
import java.util.List;
public class TestSupplier {
private int varA;
private int varB;
public TestSupplier(int varA, int varB) {
this.varA = varA;
this.varB = varB;
}
public int getA() {
return this.varA;
}
public int getB() {
return this.varB;
}
public static void main(String[] args) {
List<TestSupplier> testList = new ArrayList<>();
testList.add(new TestSupplier(1, 11));
testList.add(new TestSupplier(2, 22));
// Can I pass something like a generic supplier instead of a bool?
TestSupplier.someCollectorFunction(testList, true);
TestSupplier.someCollectorFunction(testList, false);
}
public static void someCollectorFunction(List<TestSupplier> list, boolean isA /* what if I want more than one getter*/) {
int sum = 0;
for (TestSupplier obj: list) {
// This is where I wish I could have a generic supplier or something
if (isA) {
sum = sum + obj.getA();
}
else {
sum = sum + obj.getB();
}
}
System.out.println("I have a sum: " + sum);
}
}
Is there something is Java's functional API that would let me do this?
It sounds like what you want is
ToIntFunction<TestSupplier> fn = isA ? TestSupplier::getA : TestSupplier::getB;
for (TestSupplier obj: list) {
sum += fn.applyAsInt(obj);
}
It's up to you whether you consider that an improvement.
You could also pass in the ToIntFunction instead of the boolean, passing in TestSupplier::getA instead of true etc.

Best practice for adding elements to an ArrayList during object construction?

So I'm working on a project for my online AP Computer Science class and have run into a problem... Here's the original class definition I was given to build upon (stripped of code irrelevant to my question):
Note: The constructor of the Bin class accepts a single argument, a String. The String is representative of the Bin's name.
import java.util.*;
public class Warehouse
{
// Declare instance variables here
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
// Code that will start the warehouse
// off with 5 empty bins
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
My job is to replace the areas commented out with actual code implementation. While the declaration of the instance variables is very straight forward, I'm rather torn on the best way to implement the code mentioned in the second comment.
In short, which is the best way to complete the above constructor?
Solution A:
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
for(int i = 0; i < 5; i++)
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
Solution B:
private int myBinMax;
private ArrayList<MusicMedia> myCatalog;
private ArrayList<Bin> myBins;
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( 5 );
for(int i = 0; i < 5; i++)
{
addBin(); // <= Is this considered bad practice?
}
}
Solution C:
// Some magical wizard code I would have never thought of. XD
Thanks in advance!
Can you use Java 8?
final List<Bin> bins = IntStream.range(0, 5).
mapToObj(i -> new Bin("Bin" + i)).
collect(Collectors.toCollection(ArrayList::new));
Otherwise, both your solutions looks fine. I would prefer B as you already have an addBin method with one caveat. You must make addBin final as it is a public method. You should only call private or final methods from constructors otherwise you risk someone (possibly you) overriding that method in a subclass and then the subclasses method will be called from the superclass constructor before the subclass is initialized.
try to use a constant than magic numbers in code :)
import java.util.*;
public class Warehouse
{
// Declare instance variables here
private static final int INITIAL_BINS = 5;
private static final String DEFAULT_BINNAME = "DefaultBin_";
public Warehouse( int binMax )
{
myBinMax = binMax;
myCatalog = new ArrayList<MusicMedia>();
myBins = new ArrayList<Bin>( INITIAL_BINS );
for(int i = 0; i < INITIAL_BINS; i++)
{
myBins.add( new Bin( DEFAULT_BINNAME + i ) );
//addBin();// This is fine too depends on how flexible you want naming to be:)
}
}
public void addBin()
{
myBins.add( new Bin( "B" + myBins.size() ) );
}
}
While I agree with most everything that's already been said, the java 8 functional programming style one-liner is pretty sexy. Magic numbers / strings should be avoided. If your class hasn't gone over functional style why not move the entire for loop into its own function? Generally the only thing that a constructor should do is initialize the state of your object. To make that explicit I try to keep to one line per member variable and that one line is nothing more than an initialization statement. IMO methods (which can reference the current state of the object) shouldn't be called from a constructor because your object hasn't been created yet. If you want to add functions to help you initialize your object, feel free to do so but keep them static so that the intent of the function (not referring to the state of the object) is clear.
...
private static final int INITIAL_BIN_COUNT = 5;
private static final String BIN_PREFIX = "B";
private final List<Bin> myBins;
public Warehouse(...) {
....
myBins = initMyBins();
}
private static List<Bin> initMyBins() {
final List<Bin> result = new ArrayList<Bin>(INITIAL_BIN_COUNT);
for(int i = 0; i < INITIAL_BIN_COUNT; i++) {
result.add(new Bin(BIN_PREFIX+i));
}
return result;
}
...
P.S. A few other notes, it's generally good practice to code to interface types rather than concrete class types (maybe you haven't covered interfaces yet, but that's what I did changing ArrayList to List.

Java - Increase the value of an int size method by 1 everytime the method is called

I'm stuck on this one question I can't get my head around. I need to write a method to increase the number of "votes" of a specific "act" by one and then print out the updated vote count for that specific act. I'm working with ArrayLists here as well to point out.
Here is the logic you want to follow:
1: Iterate through ArrayList of 'acts'
2: Check for specified 'act'
3: If 'act' equals specified 'act', add one to your counter variable (votes++)
This is as much information as I'll give out without code to show what you've tried!
You could use a Map:
Class VoteCounter {
Map<Integer, Integer> actToCounterMap = new HashMap<Integer, Integer>();
public void raiseVoteForAct(int actId) {
if (actToCounterMap.contains(actId) {
int curVote = actToCounterMap.get(actId);
curVote++;
actToCounterMap.put(actId, curVote);
} else {
// init to 1
actToCounterMap.put(actId, 1);
}
}
}
You can print entire objects out in java, such as
System.out.println("Array list contains: " + arrayListName);
which will print the contents of the array without iterating through each value, although it may have odd syntax. As for the "acts", which I assume you mean objects, if you want to iterate the number of votes by one, you can have a class like this:
public class Act{
int votes = 0;
public void increaseVote(){
votes ++;
//You can also do votes = votes + 1, or votes += 1, but this is the fastest.
}
//While were at it, let's add a print method!
pubic void printValue(){
System.out.println("Votes for class " + this.getClass().getName() + " = " + votes + ".");
}
}
Finally, for a class with the arrayList:
class classWithTheArrayList {
private ArrayList<Act> list = new ArrayList<Act>();
public static void main(String[] args){
Act example1 = new Act();
list.add(example1);
//ArrayLists store a value but can't be changed
//when in the arraylist, so, after updating the value like this:
Act example2 = new Act();
example2.increaseVote();
//we need to replace the object with the updated one
replaceObject(example1, example2);
}
public void replaceObject(Object objToBeRemoved, Object objToReplaceWith){
list.add(objToReplaceWith, list.indexOf(objToBeRemoved); //Add object to the same position old object is at
list.remove(objToBeRemoved); //Remove old object
}
}
A slightly more efficient vote counter.
class VoteCounter<T> {
final Map<T, AtomicInteger> actToCounterMap = new HashMap<>();
public void raiseVoteForAct(T id) {
AtomicInteger ai = actToCounterMap.get(id);
if (ai == null)
actToCounterMap.put(id, ai = new AtmoicInteger());
ai.incrementAndGet();
}
}
Instead of AtomicInteger you can use new int[1] but it's relatively ugly. ;)

is This Data Abstration Example right or not?

i had given the following code in an interview. I want to know whether it is right or not..
public class DataAbstraction
{
public static void main (String args[])
{
MyDetails obj = new MyDetails();
obj.setNumebr(10);
obj.incrementBy(20);
int num = obj.getMumber();
System.out.println(num);
}
}
class MyDetails
{
private int n;
public void setNumebr(int i)
{
n = i;
}
public void incrementBy(int i)
{
n = n + i;
}
public int getMumber()
{
return n;
}
}
So please check it and correct me if i was wrong
There are many forms of abstractions in software. I would say that this is an example of data abstraction (though I would usually call it encapsulation). You could, if you would like to, change the member variable n to be of type... String(!), without changing the public interface of MyDetails.
Put differently: The details in the MyDetails class are hidden from the client code. The fact that MyDetails stores an int is abstracted away and it could be changed, for instance like this:
class MyDetails
{
private String n; // changed internal detail
public void setNumebr(int i)
{
n = "" + i;
}
public void incrementBy(int i)
{
n = "" + getMumber() + i;
}
public int getMumber()
{
return Integer.parseInt(n);
}
}
Have a look at the Wikipedia article on data abstraction for further details:
Abstraction > Data abstraction
Since there aren't enough details in the question its guessing time again:
1) No, its wrong. it contains various spelling errors like "getMumber" and "setNumebr".
2) Yes, if we ignore the spelling errors the methods seem to do what one would expect from their names.
2) No, it doesn't launch the rocket and it doesn't scale to multi processor machines (assuming these where the requirements).

Invoking a same method just once in java

I have four different classes classA, classB, classC and classD. All the four classes have the same static method search() which takes two string parameters. If i want to invoke static method search in four different classes from main class at once. How can I do that. For now my code is as follows for main class. I need to execute the same thing for other 3 classes also. How can i do that and display the results of other 3 in the same way as for classA. The way search is done in 4 classes r different but they should give the same result.
Main() {
Object[] zy;
for (String pattern : Read.arrayList) {
List<Integer> results = ClassA.findAll(pattern, dataToSearch);
zy = results.toArray();
for (int i = 0; i < zy.length; i++) {
System.out.println(" Pattern searched " + pattern + " match is found at index : "+ results);
}
}
if (zy.length == 0) {
System.out.println("Nothing matched");
}
}
I strongly recommend you change this to non-static methods. Look how easy and nice is when you will seperate an interface:
public interface Common {
List<Integer> findAll(String pattern, String dataToSearch);
}
public class A implements Common ...
public class B implements Common ...
public class C implements Common ...
public class D implements Common ...
// in main:
List<Common> allYourClasses = new ArrayList<Common>();
allYourClasses.add(new A());
allYourClasses.add(new B());
allYourClasses.add(new C());
allYourClasses.add(new D());
List<Integer> result = new ArrayList<Integer>();
for (Common c : allYourClasses) {
result.addAll(c.findAll(pattern, dataToSearch));
}
1 - You should NOT do this. Avoid static methods. One of the reason being they can not be called without the exact class. A group of classes that implement a simple interfaces will work faster, safer and better in every way
2 - You can (but you shouldn't) do something like this:
for (Class<?> clazz : new Class[] { ClassA.class, ClassB.class,
ClassC.class }) {
Object[] zy = null;
String dataToSearch = "";
String[] arrayList = { "a" };
for (String pattern : arrayList) {
List<Integer> results = findAllForClass(clazz, pattern,
dataToSearch);
zy = results.toArray();
for (int i = 0; i < zy.length; i++) {
System.out.println(" Pattern searched " + pattern
+ " match is found at index : " + results);
}
}
if (zy.length == 0) {
System.out.println("Nothing matched");
}
}
#SuppressWarnings("unchecked")
public static List<Integer> findAllForClass(Class<?> clazz, String pattern,
String dataToSearch) {
List<Integer> list = null;
try {
list = (List<Integer>) clazz.getDeclaredMethod("findAll", String.class,
String.class).invoke(null, pattern, dataToSearch);
} catch (Exception e) {
list = Collections.emptyList();
}
return list;
}
You see the #supresswarning and the try/catch? well, this is a hint: is telling you you this code is at least suspicious. It is in fact unsafe, non well performant, and is a stupid workaround.
(But we all did something like that once in our lives)
I can't really figure out why would anyone do that.
That said, you could have a method taking a Class as a parameter and calling the method explicitly by name (getMethod.../invoke()).
That puts you back in non static world and you can iterate over the classes you want to invoke. (But again, why use statics in the first place?)
Pseudo untested code:
public void invokeStatic(Class clazz, String method, Class<?> paramsTypes[], Object[] params) {
Method method = clazz.getMethod(method, paramsType);
method.invoke(params);
}
If you want to group all of the results together, just keep adding results to your list:
List<Integer> results = ClassA.findAll(pattern, dataToSearch);
results.addAll(ClassB.findAll(pattern, dataToSearch));
// etc.

Categories