I'm developing a game and there are tons of occasions where I need some sort of factory pattern involved.
In an attempt not to create lots of Factory class methods, I used Supplier<T> instead. This works great but not if there are required arguments.
It works in this case: () -> new Spawn(3, 6, "example");
But sometimes I need to pass other parameters to the factory.
There's the Consumer and BiConsumer which accept two parameters. But there's no interface for 3, 4, 5...
I came up with an embarassing solution to this problem, but it illustrates what I'm trying to achieve. What other solutions are there?
import java.util.function.Function;
public class FactoryExample {
static class Args {
Object[] objs;
Args(Object ...objs) { this.objs = objs; }
Object[] get() { return objs; }
}
static class Thing {
int a; char b; boolean c;
Thing(int a, char b, boolean c) {
this.a = a; this.b = b; this.c = c; }
}
static class Number {
int x;
Number(int x) { this.x = x; }
}
public static void main(String[] args) {
Function<Args, Number> factoryA = arg -> {
int x = (int) arg.get()[0];
return new Number(x);
};
Function<Args, Thing> factoryB = arg -> {
int a = (int) arg.get()[0];
char b = (char) arg.get()[1];
boolean c = (boolean) arg.get()[2];
return new Thing(a, b, c);
};
factoryB.apply(new Args(3, 'a', true));
factoryA.apply(new Args(3));
}
}
Example: how do I avoid creating a bunch of these factories?
public class InfectionFactory {
private Integer damage;
private Integer delay;
private Integer hits;
private Integer spikes;
private Color color;
public InfectionFactory setColor(Color color) {
this.color = color;
return this;
}
public InfectionFactory setSpikes(int spikes) {
this.spikes = spikes;
return this;
}
public InfectionFactory setDamage(int damage) {
this.damage = damage;
return this;
}
public InfectionFactory setDelay(int delay) {
this.delay = delay;
return this;
}
public InfectionFactory setHits(int hits) {
this.hits = hits;
return this;
}
public Infection create(Game game, Living target) {
Infection infection = new Infection(game, target);
if (damage != null) infection.setDamage(damage);
if (color != null) infection.setColor(color);
if (delay != null) infection.setDelay(delay);
if (hits != null) infection.setHits(hits);
if (spikes != null) infection.setSpikes(spikes);
return infection;
}
}
You seem to have multiple requirements. First of all, to make the Supplier take all the arguments you want, you can do something like:
public class SpawnFactory implements Supplier<Spawn> {
//todo: put members for all the arguments you need, make them final so that you don't miss any in the constructor
public SpawnFactory( ... all the arguments you want ... ) {
}
public Spawn get() {
return new Spawn( ... all the arguments you want ...);
}
}
Since it implements Supplier, you can pass them directly instantiated the way you like. Instead of () -> new Spawn(3, 6, "example") just do new SpawnFactory(3, 6, "example");
The example of your InfectionFactory on the other hand is following the builder pattern (you might want to rename it InfectionBuilder). Nothing is wrong with this (apart from the fact that it seems a bit redundant since Infection is using the same pattern too)
You might want to make it take the Game and Living as constructor arguments instead, and then your create() will not need any arguments. Your last step would be to make the class implement Supplier<Infection> and add Infection get() which just calls create() (unless you want to rename create() to get()).
Related
In this Java class, note how use of the constructor has been disallowed and replaced with an interface driven builder that guides instantiation and does validation
public class Position implements Serializable {
private BigDecimal capital;
private BigDecimal tolerableRiskInPercentOfCapitalPerTrade;
private Direction direction;
private BigDecimal pricePerUnit;
private BigDecimal stopLossPricePerUnit;
private Position(){}
public final BigDecimal getTotalTolerableRiskPerTrade() {
return capital.multiply(tolerableRiskInPercentOfCapitalPerTrade.divide(new BigDecimal(100)));
}
public final BigDecimal getStopLossPerUnitLoss() {
if (direction.equals(Direction.LONG)){
return pricePerUnit.subtract(stopLossPricePerUnit);
} else {
return stopLossPricePerUnit.subtract(pricePerUnit);
}
}
public final BigDecimal getStopLossTotalLoss() {
return getStopLossPerUnitLoss().multiply(getUnitsToBuy());
}
public final BigDecimal getUnitsToBuy() {
BigDecimal result = getTotalTolerableRiskPerTrade().divide(getStopLossPerUnitLoss(), 0, BigDecimal.ROUND_DOWN);
if (capital.compareTo(result.multiply(pricePerUnit)) != 1){
return new BigDecimal(0);
} else {
return result;
}
}
public final BigDecimal getTotal() {
return getUnitsToBuy().multiply(pricePerUnit);
}
public static ICapital builder(){
return new Builder();
}
public interface ICapital {
ITolerableRiskInPercentOfCapitalPerTrade capital(final BigDecimal capital);
}
public interface ITolerableRiskInPercentOfCapitalPerTrade {
IDirection tolerableRiskInPercentOfCapitalPerTrade(final BigDecimal tolerableRiskInPercentOfCapitalPerTrade);
}
public interface IDirection {
IPricePerUnit direction(final Direction direction);
}
public interface IPricePerUnit {
IStopLossPricePerUnit pricePerUnit(final BigDecimal pricePerUnit);
}
public interface IStopLossPricePerUnit {
IBuild stopLossPricePerUnit(final BigDecimal stopLossPricePerUnit);
}
public interface IBuild {
Position build();
}
private static class Builder implements ICapital, ITolerableRiskInPercentOfCapitalPerTrade, IDirection, IPricePerUnit, IStopLossPricePerUnit, IBuild {
private final Position instance = new Position();
#Override
public Position build() {
return instance;
}
#Override
public ITolerableRiskInPercentOfCapitalPerTrade capital(final BigDecimal capital) {
basicValidate(capital);
instance.capital = capital;
return this;
}
#Override
public IDirection tolerableRiskInPercentOfCapitalPerTrade(final BigDecimal tolerableRiskInPercentOfCapitalPerTrade) {
basicValidate(tolerableRiskInPercentOfCapitalPerTrade);
if (tolerableRiskInPercentOfCapitalPerTrade.compareTo(new BigDecimal(100)) != -1) {
throw new IllegalArgumentException("riskInPercent must be lower than 100");
}
instance.tolerableRiskInPercentOfCapitalPerTrade = tolerableRiskInPercentOfCapitalPerTrade;
return this;
}
#Override
public IPricePerUnit direction(final Direction direction) {
if (direction==null) {
throw new IllegalArgumentException("argument can't be null");
}
instance.direction = direction;
return this;
}
#Override
public IStopLossPricePerUnit pricePerUnit(final BigDecimal pricePerUnit) {
basicValidate(pricePerUnit);
instance.pricePerUnit = pricePerUnit;
return this;
}
#Override
public IBuild stopLossPricePerUnit(final BigDecimal stopLossPricePerUnit) {
basicValidate(stopLossPricePerUnit);
if (instance.direction.equals(Direction.LONG) && instance.pricePerUnit.compareTo(stopLossPricePerUnit) != 1) {
throw new IllegalArgumentException("price must be higher than stopLossPrice");
}
if (instance.direction.equals(Direction.SHORT) && stopLossPricePerUnit.compareTo(instance.pricePerUnit) != 1) {
throw new IllegalArgumentException("stopLossPrice must be higher than price");
}
instance.stopLossPricePerUnit = stopLossPricePerUnit;
return this;
}
}
protected static void basicValidate(final BigDecimal bigDecimal) {
if (bigDecimal == null) {
throw new IllegalArgumentException("argument can't be null");
}
if (!(bigDecimal.signum() > 0)) {
throw new IllegalArgumentException("argument must have positive signum");
}
}
}
resulting in instantiation like this
Position.builder()
.capital(new BigDecimal(10000))
.tolerableRiskInPercentOfCapitalPerTrade(new BigDecimal(2))
.direction(Direction.LONG)
.pricePerUnit(new BigDecimal(25))
.stopLossPricePerUnit(new BigDecimal(24))
.build();
Trying to port code between languages isn't easy and identical functionality can't and shouldn't be expected. That said, are there any ways of emulating similar functionality in JavaScript? (vanilla or through some modules/libraries if necessary)
There are a few ways to do this.
One option is to do it almost exactly the same way: With a builder object that has methods to specify details and a build method (or similar) that you call to get the final object. The resulting call to build the object would look almost exactly the same (modulo type names and such).
Another option is to take advantage of JavaScript's object initializer syntax (aka "object literals") to have an "options" object that you pass into a constructor for the Position, like this:
function Position(options) {
if (/*...the options aren't valid...*/) {
throw new Error(/*...*/);
}
this.capital = options.capital;
// ...
}
Usage:
var p = new Position({
capital: 10000,
tolerableRiskInPercentOfCapitalPerTrade: 2,
direction: Direction.LONG,
pricePerUnit: 25,
stopLossPricePerUnit: 24
});
Inside the constructor, if you're going to use the data from options directly as properties on the new instance, you can use a function top copy them over:
function applyOptions(instance, options) {
Object.keys(options).forEach(function(key) {
instance[key] = options[key];
});
return instance;
}
Then:
function Position(options) {
if (/*...the options aren't valid...*/) {
throw new Error(/*...*/);
}
applyOptions(this, options);
}
(jQuery, if you use it, has an $.extend function that basically does this; Underscore, if you use it, has _.extend and _.extendOwn.)
But if you're going to be doing some manipulation of the options before storing them as properties on the new instance, a blind copy like that wouldn't be ideal.
I am a beginner in Java and i trying to understand the abstract classes.
Below is the code that I've written; the question is: how do i write a method that will return an instance of that class.
public abstract class VehicleEngine
{
protected String name;
protected double fabricationCons;
protected double consum;
protected int mileage;
public VehicleEngine(String n, double fC)
{
name = n;
fabricationCons = fC;
mileage = 0;
consum = 0;
}
private void setFabricationCons(double fC)
{
fabricationCons = fC;
}
public abstract double currentConsum();
public String toString()
{
return name + " : " + fabricationCons + " : " + currentConsum();
}
public void addMileage(int km)
{
mileage += km;
}
public double getFabricationConsum()
{
return fabricationCons;
}
public String getName()
{
return name;
}
public int getMileage()
{
return mileage;
}
//public VehicleEngine get(String name){
//if(getName().equals(name)){
//return VehicleEngine;
//}
//return null;
//}
}
public class BenzinVehicle extends VehicleEngine
{
public BenzinVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
if (getMileage() >= 75000) {
consum = getFabricationConsum() + 0.4;
} else {
consum = getFabricationConsum();
}
return consum;
}
}
public class DieselVehicle extends VehicleEngine
{
public DieselVehicle(String n, double fC)
{
super(n, fC);
}
#Override
public double currentConsum()
{
int cons = 0;
if (getMileage() < 5000) {
consum = getFabricationConsum();
} else {
consum = getFabricationConsum() + (getFabricationConsum() * (0.01 * (getMileage() / 5000)));
}
return consum;
}
}
This is the main.
public class Subject2
{
public static void main(String[] args)
{
VehicleEngine c1 = new BenzinVehicle("Ford Focus 1.9", 5.0);
DieselVehicle c2 = new DieselVehicle("Toyota Yaris 1.4D", 4.0);
BenzinVehicle c3 = new BenzinVehicle("Citroen C3 1.6",5.2);
c1.addMileage(30000);
c1.addMileage(55700);
c2.addMileage(49500);
c3.addMileage(35400);
System.out.println(c1);
System.out.println(c2);
System.out.println(VehicleEngine.get("Citroen C3 1.6")); //this is the line with problems
System.out.println(VehicleEngine.get("Ford Focus "));
}
}
And the output should be:
Ford Focus 1.9 : 5.0 : 5.4
Toyota Yaris 1.4D : 4.0 : 4.36
Citroen C3 1.6 : 5.2 : 5.2
null
You can not return an instance of an abstract class, by definition. What you can do, is return an instance of one of the concrete (non-abstract) subclasses that extend it. For example, inside the VehicleEngine you can create a factory that returns instances given the type of the instance and the expected parameters, but those instances will necessarily have to be concrete subclasses of VehicleEngine
Have a look at the Factory Method pattern. Your concrete classes will implement an abstract method that returns a class instance.
Abstract classes do not keep a list of their instances. Actually no Java class does that. If you really want to do that, you could add a static map to VehicleEngine like this:
private static Map<String, VehicleEngine> instanceMap = new HashMap<String, VehicleEngine>();
and change your get method to a static one like this:
public static VehicleEngine get(String name) {
return instanceMap.get(name);
}
and add this line to the end of the constructor of VehicleEngine:
VehicleEngine.instanceMap.put(n, this);
this way every new instance created puts itself into the static map. However this actually is not a good way to implement such a functionality. You could try to use a factory to create instances, or you could consider converting this class into an enum if you will have a limited predefined number of instances.
Is it possible to get a Field through Java reflection if I have the field itself? It's a primitive float (public, no problem). I don't want to use its name as a String.
Example:
public class TVset {
public float voltageA;
public float voltageB;
public float voltageC;
public TVset(...) {...} // constructor
public void function() {...} // it changes voltages
}
class Voltmeter{
Object theObject;
Field theField;
Voltmeter(Object obj) {
theObject = obj;
Class theFieldClass = obj.getClass();
Class theContainerClass = theFieldClass.getDeclaringClass();
Field theField = ??? // <-- here I don't want to use a String
}
float getVoltage() {
return theField.getFloat(theObject);
}
}
TVset tv1 = new TVset(...);
TVset tv2 = new TVset(...);
Voltmeter meter = new Voltmeter(tv1.voltageB);
meter.getVoltage();
tv1.function();
meter.getVoltage(); <- should reflect the changed voltage
tv1.function();
meter.getVoltage(); <- should reflect the changed voltage
...
The effect is similar to passing the float by reference, but without wrapping it into a wrapper class.
I need to measure different voltages on different TV sets, just by changing the line:
Voltmeter meter = new Voltmeter(tv1.voltageB);
to something else, like:
Voltmeter meter = new Voltmeter(tv2.voltageA);
Is it possible to do it with reflection?
Thx
To use reflection you have to use a String. Instead of using a float you can use an object to wrap mutable float or a simple float[1];
BTW I wouldn't use float unless you have a really good reason, double suffers far less rounding error.
public class TVset {
public double[] voltageA = { 0.0 };
public double[] voltageB = { 0.0 };
public double[] voltageC = { 0.0 };
}
class Voltmeter{
final double[] theField;
Voltmeter(double[] theField) {
this.theField = theField;
}
double getVoltage() {
return theField[0];
}
}
// works just fine.
Voltmeter meter = new Voltmeter(tv1.voltageB);
EDIT: Using an abstract accessor. This is the fastest way to do this. AFAIK,the difference is less than 10 nano-seconds.
public abstract class Voltmeter{ // or use an interface
public abstract double get();
public abstract void set(double voltage);
}
public class TVset {
private double _voltageA = 0.0;
private double _voltageB = 0.0;
private double _voltageC = 0.0;
public final Voltmeter voltageA = new Voltmeter() {
public double get() { return _voltageA; }
public void set(double voltage) { _voltageA = voltage; }
}
public final Voltmeter voltageB = new Voltmeter() {
public double get() { return _voltageB; }
public void set(double voltage) { _voltageB = voltage; }
}
public final Voltmeter voltageC = new Voltmeter() {
public double get() { return _voltageC; }
public void set(double voltage) { _voltageC = voltage; }
}
}
Personally, if speed is critical, I would just use the fields directly by name. You won't get simpler or faster than that.
Just for completeness I've included the delegate way of solving this. I would also not recommend having your floats with public access.
public class stackoverflow_5383947 {
public static class Tvset {
public float voltageA;
public float voltageB;
public float voltageC;
public Tvset() {
}
public void function() {
voltageA++;
}
};
public static class Voltmeter {
private VoltageDelegate _delegate;
public Voltmeter(VoltageDelegate delegate) {
_delegate = delegate;
}
float getVoltage() {
return _delegate.getVoltage();
}
};
public static interface VoltageDelegate {
public float getVoltage();
}
public static void main(String[] args) {
final Tvset tv1 = new Tvset();
Voltmeter meter = new Voltmeter(new VoltageDelegate() {
public float getVoltage() {
return tv1.voltageA;
}
});
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
tv1.function();
System.out.println(meter.getVoltage());
}
}
If you control the TVSet but need to use reflection for some reason, a good way to avoid errors is to write the method/field names that you need as String Constants in the TVSet class.
However if your concern is performance, reflection is not the way to go because accessing a field or method through reflection can be much slower than accessing through getters or directly.
Here a variant where you can give your float value instead of a string.
class Voltmeter{
Object container;
Field theField;
Voltmeter(Object obj, float currentValue) {
container = obj;
Class<?> containerClass = obj.getClass();
Field[] fields = containerClass.getFields();
for(Field f : fields) {
if (f.getType() == float.class &&
f.getFloat(container) == currentValue) {
this.theField = f;
break;
}
}
}
float getVoltage() {
return theField.getFloat(container);
}
}
Then call it like this:
Voltmeter meter = new Voltmeter(tv1, tv1.voltageB);
It works only if the voltages in the moment of Voltmeter creation are different (and not NaN), as it takes the first Field with the right value. And it is not really more efficient, I think.
I wouldn't really recommend this.
I am trying to return 2 values from a Java method but I get these errors. Here is my code:
// Method code
public static int something(){
int number1 = 1;
int number2 = 2;
return number1, number2;
}
// Main method code
public static void main(String[] args) {
something();
System.out.println(number1 + number2);
}
Error:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - missing return statement
at assignment.Main.something(Main.java:86)
at assignment.Main.main(Main.java:53)
Java Result: 1
Instead of returning an array that contains the two values or using a generic Pair class, consider creating a class that represents the result that you want to return, and return an instance of that class. Give the class a meaningful name. The benefits of this approach over using an array are type safety and it will make your program much easier to understand.
Note: A generic Pair class, as proposed in some of the other answers here, also gives you type safety, but doesn't convey what the result represents.
Example (which doesn't use really meaningful names):
final class MyResult {
private final int first;
private final int second;
public MyResult(int first, int second) {
this.first = first;
this.second = second;
}
public int getFirst() {
return first;
}
public int getSecond() {
return second;
}
}
// ...
public static MyResult something() {
int number1 = 1;
int number2 = 2;
return new MyResult(number1, number2);
}
public static void main(String[] args) {
MyResult result = something();
System.out.println(result.getFirst() + result.getSecond());
}
Java does not support multi-value returns. Return an array of values.
// Function code
public static int[] something(){
int number1 = 1;
int number2 = 2;
return new int[] {number1, number2};
}
// Main class code
public static void main(String[] args) {
int result[] = something();
System.out.println(result[0] + result[1]);
}
You could implement a generic Pair if you are sure that you just need to return two values:
public class Pair<U, V> {
/**
* The first element of this <code>Pair</code>
*/
private U first;
/**
* The second element of this <code>Pair</code>
*/
private V second;
/**
* Constructs a new <code>Pair</code> with the given values.
*
* #param first the first element
* #param second the second element
*/
public Pair(U first, V second) {
this.first = first;
this.second = second;
}
//getter for first and second
and then have the method return that Pair:
public Pair<Object, Object> getSomePair();
You can only return one value in Java, so the neatest way is like this:
return new Pair<Integer>(number1, number2);
Here's an updated version of your code:
public class Scratch
{
// Function code
public static Pair<Integer> something() {
int number1 = 1;
int number2 = 2;
return new Pair<Integer>(number1, number2);
}
// Main class code
public static void main(String[] args) {
Pair<Integer> pair = something();
System.out.println(pair.first() + pair.second());
}
}
class Pair<T> {
private final T m_first;
private final T m_second;
public Pair(T first, T second) {
m_first = first;
m_second = second;
}
public T first() {
return m_first;
}
public T second() {
return m_second;
}
}
Here is the really simple and short solution with SimpleEntry:
AbstractMap.Entry<String, Float> myTwoCents=new AbstractMap.SimpleEntry<>("maximum possible performance reached" , 99.9f);
String question=myTwoCents.getKey();
Float answer=myTwoCents.getValue();
Only uses Java built in functions and it comes with the type safty benefit.
Use a Pair/Tuple type object , you don't even need to create one if u depend on Apache commons-lang. Just use the Pair class.
you have to use collections to return more then one return values
in your case you write your code as
public static List something(){
List<Integer> list = new ArrayList<Integer>();
int number1 = 1;
int number2 = 2;
list.add(number1);
list.add(number2);
return list;
}
// Main class code
public static void main(String[] args) {
something();
List<Integer> numList = something();
}
public class Mulretun
{
public String name;;
public String location;
public String[] getExample()
{
String ar[] = new String[2];
ar[0]="siva";
ar[1]="dallas";
return ar; //returning two values at once
}
public static void main(String[] args)
{
Mulretun m=new Mulretun();
String ar[] =m.getExample();
int i;
for(i=0;i<ar.length;i++)
System.out.println("return values are: " + ar[i]);
}
}
o/p:
return values are: siva
return values are: dallas
I'm curious as to why nobody has come up with the more elegant callback solution. So instead of using a return type you use a handler passed into the method as an argument. The example below has the two contrasting approaches. I know which of the two is more elegant to me. :-)
public class DiceExample {
public interface Pair<T1, T2> {
T1 getLeft();
T2 getRight();
}
private Pair<Integer, Integer> rollDiceWithReturnType() {
double dice1 = (Math.random() * 6);
double dice2 = (Math.random() * 6);
return new Pair<Integer, Integer>() {
#Override
public Integer getLeft() {
return (int) Math.ceil(dice1);
}
#Override
public Integer getRight() {
return (int) Math.ceil(dice2);
}
};
}
#FunctionalInterface
public interface ResultHandler {
void handleDice(int ceil, int ceil2);
}
private void rollDiceWithResultHandler(ResultHandler resultHandler) {
double dice1 = (Math.random() * 6);
double dice2 = (Math.random() * 6);
resultHandler.handleDice((int) Math.ceil(dice1), (int) Math.ceil(dice2));
}
public static void main(String[] args) {
DiceExample object = new DiceExample();
Pair<Integer, Integer> result = object.rollDiceWithReturnType();
System.out.println("Dice 1: " + result.getLeft());
System.out.println("Dice 2: " + result.getRight());
object.rollDiceWithResultHandler((dice1, dice2) -> {
System.out.println("Dice 1: " + dice1);
System.out.println("Dice 2: " + dice2);
});
}
}
You don't need to create your own class to return two different values. Just use a HashMap like this:
private HashMap<Toy, GameLevel> getToyAndLevelOfSpatial(Spatial spatial)
{
Toy toyWithSpatial = firstValue;
GameLevel levelToyFound = secondValue;
HashMap<Toy,GameLevel> hm=new HashMap<>();
hm.put(toyWithSpatial, levelToyFound);
return hm;
}
private void findStuff()
{
HashMap<Toy, GameLevel> hm = getToyAndLevelOfSpatial(spatial);
Toy firstValue = hm.keySet().iterator().next();
GameLevel secondValue = hm.get(firstValue);
}
You even have the benefit of type safety.
Return an Array Of Objects
private static Object[] f ()
{
double x =1.0;
int y= 2 ;
return new Object[]{Double.valueOf(x),Integer.valueOf(y)};
}
In my opinion the best is to create a new class which constructor is the function you need, e.g.:
public class pairReturn{
//name your parameters:
public int sth1;
public double sth2;
public pairReturn(int param){
//place the code of your function, e.g.:
sth1=param*5;
sth2=param*10;
}
}
Then simply use the constructor as you would use the function:
pairReturn pR = new pairReturn(15);
and you can use pR.sth1, pR.sth2 as "2 results of the function"
You also can send in mutable objects as parameters, if you use methods to modify them then they will be modified when you return from the function. It won't work on stuff like Float, since it is immutable.
public class HelloWorld{
public static void main(String []args){
HelloWorld world = new HelloWorld();
world.run();
}
private class Dog
{
private String name;
public void setName(String s)
{
name = s;
}
public String getName() { return name;}
public Dog(String name)
{
setName(name);
}
}
public void run()
{
Dog newDog = new Dog("John");
nameThatDog(newDog);
System.out.println(newDog.getName());
}
public void nameThatDog(Dog dog)
{
dog.setName("Rutger");
}
}
The result is:
Rutger
You can create a record (available since Java 14) to return the values with type safety, naming and brevity.
public record MyResult(int number1, int number2) {
}
public static MyResult something() {
int number1 = 1;
int number2 = 2;
return new MyResult(number1, number2);
}
public static void main(String[] args) {
MyResult result = something();
System.out.println(result.number1() + result.number2());
}
First, it would be better if Java had tuples for returning multiple values.
Second, code the simplest possible Pair class, or use an array.
But, if you do need to return a pair, consider what concept it represents (starting with its field names, then class name) - and whether it plays a larger role than you thought, and if it would help your overall design to have an explicit abstraction for it. Maybe it's a code hint...
Please Note: I'm not dogmatically saying it will help, but just to look, to see if it does... or if it does not.
I have a method that is producing side effects, even though certain variables are marked final. Why is this? Perhaps I am confused about what final does.
#Test
public void testSubGraph() {
WeightedGraph<String, DefaultWeightedEdge> g = generateSimpleCaseGraph();
Graph<String, DefaultWeightedEdge> sub = ChooseRoot.subgraphInDirection(g, "alpha", "l");
assertEquals(g, generateSimpleCaseGraph()); //fails
}
public static <V, E extends DefaultEdge> Graph<V, E> subgraphInDirection(final Graph<V, E> g, final V start, final V sink) {
Graph<V, E> sub = removeEdges(g, start, sink);
return removeUnconnectedNodes(sub, start);
}
private static <Vertex, Edge extends DefaultEdge> Graph<Vertex, Edge> removeEdges(final Graph<Vertex, Edge> g, Vertex start, Vertex sink) {
final Set<Edge> outEdges = new HashSet<Edge>(g.edgesOf(start));
boolean removedEdge;
for (Edge e : outEdges) {
if (! (g.getEdgeTarget(e).equals(sink) || g.getEdgeSource(e).equals(sink))) {
removedEdge = g.removeEdge(e);
assert removedEdge;
}
}
return g;
}
private static <Vertex, Edge> Graph<Vertex, Edge> removeUnconnectedNodes(Graph<Vertex, Edge> g, Vertex start) {
ConnectivityInspector<Vertex, Edge> conn = new ConnectivityInspector<Vertex, Edge>((UndirectedGraph<Vertex, Edge>) g);
boolean removedVertex;
final Set<Vertex> nodes = new HashSet<Vertex>(g.vertexSet());
for (Vertex v : nodes) {
if (! conn.pathExists(start, v)) {
removedVertex = g.removeVertex(v);
assert removedVertex;
}
}
return g;
}
The final modifier only means that the reference cannot be reassigned. It does not prevent the object's state from being modified.
EDIT: Just for Tom:
public void doSomething1(Object arg)
{
arg = new Object(); // OK.
}
public void doSomething2(final Object arg)
{
arg = new Object(); // Compile error.
}
In both cases you can invoke methods on the object pointed to by arg, including methods that modify its state.
Dan has the right answer on final. What you are after is more like const in C++, which Java does not have. You can simulate it by doing this:
public class Foo
{
protected int x;
public Foo(final int val)
{
x = val;
}
public int getX()
{
return (x);
}
}
public class MutableFoo
extends Foo
{
public MutableFoo(final int val)
{
super(val);
}
public void setX(final int val)
{
x = val;
}
}
then do:
void bar(final Foo foo)
{
foo.setX(5); // will not compile
}
void bar(final MutableFoo foo)
{
foo.setX(5); // will compile
}
Not pretty, but it works. The trick is to make sure that none of the methods in the parent class (Foo) make any changes to the instance variables - only MutableFoo can have methods that allow the state to change.
Of course the best thing to do, as much as possible, is to write immutable classes (make all the variables final) and do not call methods on instance/class variables that have side effects, so that things cannot change