I have three different types of parameters: int, float and long. I want to use an object to represent each of them. So i have one abstract class:
abstract public class AbstractProtocolParamObj<T extends Number>
{
public enum ProtocolParamConstraintTypeEnum
{
None,
OnOff,
Values,
ValueRange,
ValueRangeIncrement
}
protected String name;
protected ProtocolParamConstraintTypeEnum constraintValueType;
protected Vector<AbstractProtocolParamObj<T>> dependentParams;
protected Vector<AbstractProtocolParamObj<T>> constraintParams;
protected T value;
protected AbstractProtocolParamObj(String name,
ProtocolParamConstraintTypeEnum constraintValueType,
T value)
{
this.name = name;
this.constraintValueType = constraintValueType;
this.value = value;
}
public final String getName()
{
return name;
}
public final ProtocolParamConstraintTypeEnum getConstraintValueType()
{
return constraintValueType;
}
public void addDependentParam(AbstractProtocolParamObj<T> param)
{
if(dependentParams == null)
{
dependentParams = new Vector<AbstractProtocolParamObj<T>>();
}
dependentParams.add(param);
}
public void addConstraintParam(AbstractProtocolParamObj<T> param)
{
if(constraintParams == null)
{
constraintParams = new Vector<AbstractProtocolParamObj<T>>();
}
constraintParams.add(param);
}
public Vector<AbstractProtocolParamObj<T>> getDependentParams()
{
return dependentParams;
}
public Vector<AbstractProtocolParamObj<T>> getConstraintParams()
{
return constraintParams;
}
public T getValue()
{
return value;
}
public void setValue(T val)
{
value = val;
}
abstract public ReturnStatusEnum validate(T tempVal);
}
Then I will have one class for float parameters, one class for int and one for long. Like this:
public class ProtocolFloatParamObj extends AbstractProtocolParamObj
{
private float[] constraintVals;
private float maxVal;
private float minVal;
private float increment;
public ProtocolFloatParamObj(String name,
float value,
float[] constraintVals,
ProtocolParamConstraintTypeEnum constraintType
)
{
super(name, constraintType, value);
this.constraintVals = constraintVals;
}
public ProtocolFloatParamObj(String name,
float value,
float maxVal,
float minVal,
ProtocolParamConstraintTypeEnum constraintType
)
{
super(name, constraintType, value);
this.maxVal = maxVal;
this.minVal = minVal;
}
public ProtocolFloatParamObj(String name,
float value,
float maxVal,
float minVal,
float increment,
ProtocolParamConstraintTypeEnum constraintType
)
{
this(name, value, maxVal, minVal, constraintType);
this.increment = increment;
}
#Override
public ReturnStatusEnum validate(Number val)
{
ReturnStatusEnum status = ReturnStatusEnum.SUCCESS;
float tempVal = val.floatValue();
switch(constraintValueType)
{
case None:
{
break;
}
case OnOff:
{
break;
}
case Values:
{
break;
}
case ValueRange:
{
break;
}
case ValueRangeIncrement:
{
break;
}
}
return status;
}
}
Above code has no compile error but do has warnings which complain the generic type should be parameterized in subclass at the following lines:
public class ProtocolFloatParamObj extends AbstractProtocolParamObj
super(name, constraintType, value);
But if i change
public class ProtocolFloatParamObj extends AbstractProtocolParamObj
to
public class ProtocolFloatParamObj <T extends Number> extends AbstractProtocolParamObj<T>
and change the constructor value parameter from float to T. then everything looks good without compile error and warning.
The issue is because the ProtocolFloatParamObj constructor has a T parameter, its user/caller needs to define the T and it's easy to get warning or compile error.
For example in another class, I try to create a Vector contains some of those parameter objs but I cannot eliminate warnings or I cannot add to the objs vector:
public Vector<AbstractProtocolParamObj<T>> getAxialParamObjs()
{
Vector<AbstractProtocolParamObj<T>> objs = new Vector<AbstractProtocolParamObj<T>>();
ProtocolFloatParamObj<T> scanSpeed = new ProtocolFloatParamObj("scanSpeed",
new Float(Float.parseFloat(m_axialDefaultConfig.getProperty("scanSpeed"))),
new float[]{0.5f, 0.8f, 1.0f, 1.5f, 2.0f},
ProtocolParamConstraintTypeEnum.Values
);
objs.add(scanSpeed);
......
return objs;
}
It seems this is not a good idea or i need read more about java generic.
Do you have a better idea and do you have any advanced java generic tutorial links?
Try the following:
public class ProtocolFloatParamObj extends AbstractProtocolParamObj<Float>
Which should assign Float as the type parameter T of the super class.
Why not doing it like:
public class ProtocolFloatParamObj extends AbstractProtocolParamObj<Float>{
....
}
Change
AbstractProtocolParamObj<T> to AbstractProtocolParamObj<Float>
and change
ProtocolFloatParamObj <T extends Number> to only ProtocolFloatParamObj
resulting in
public class ProtocolFloatParamObj extends AbstractProtocolParamObj<Float>
Related
As I'm going though the debugger it looks like it is working at first, however when I try calling getCoordinates() in my shipSunk() method, it returns a null value almost every time. What is wrong here?
public boolean shipSunk(ShipDerived[] s){
ArrayListMultimap<Integer, Integer> temp;
ArrayList<Integer> temp2 = new ArrayList<>();
boolean sunk = false;
for(int i=s.length-1; i>=0;i--){
Ship st = s[i];
temp = s[i].getCoordinates(); //returns null almost every time???
temp2 = s[i].getCoordinatesList();
for (Map.Entry<Integer, Integer> entry : temp.entries()){
//System.out.println(entry.getKey() + ", " + entry.getValue());
if(grid[entry.getKey()][entry.getValue()]=='x'){
sunk = true;
}
else{
sunk = false;
}
}
if(sunk==true){
System.out.println("Ship has been sunk!");
}
temp.clear();
}
return sunk;
}
And here is my Ship class (extended from abstract class) methods:
import java.util.ArrayList;
public class ShipDerived extends Ship{
private String type;
private int length;
private ArrayListMultimap<Integer, Integer> coordinates = ArrayListMultimap.create();
private ArrayList<Integer> c2 = new ArrayList<>();
public ShipDerived(){
this.type = type;
this.length = length;
this.coordinates = getCoordinates();
this.c2 = getCoordinatesList();
}
public ShipDerived(String t, int l){
this.type = t;
this.length = l;
this.coordinates = getCoordinates();
this.c2 = getCoordinatesList();
}
#Override
void setType(String t) {
type = t;
}
#Override
void setLength(int l) {
length = l;
}
#Override
String getType() {
return type;
}
#Override
int getLength() {
return length;
}
#Override
ArrayListMultimap<Integer, Integer> getCoordinates() {
return this.coordinates;
}
ArrayList<Integer> getCoordinatesList() {
return this.c2;
}
#Override
void setCoordinates(int i, int j) {
//coordinates.putAll(i, Collections.singleton(j));
this.coordinates.put(i,j);
this.c2.add(i);
this.c2.add(j);
}
}
Here is my Ship (abstract) class:
public abstract class Ship {
private int length;
private String type;
private ArrayListMultimap<Integer, Integer> coordinates;
Ship(){
this.length = length;
this.type = type;
}
abstract void setType(String t);
abstract void setLength(int l);
abstract String getType();
abstract int getLength();
abstract ArrayListMultimap<Integer, Integer> getCoordinates();
abstract void setCoordinates(int i, int j);
}
And this is what I am passing into my shipSunk() method. I an using getters/setters to create my ships:
p1board.shipSunk(p1.getShips()); //player 1
p2board.shipSunk(p2.getShips()); //player 2
These seem to work but here's some code into these as well:
public class Player {
private String name;
private ShipDerived[] ships = new ShipDerived[5];
public Player(){
this.name = name;
this.ships = ships;
}
public String getName(){
return name;
}
public void setName(String x){
name = x;
}
public void setShips(){
int a = 0;
for(int i=5; i>=1;i--){
ShipDerived s = new ShipDerived("null", 0);
Array.set(ships, a, s);
a++;
}
ships[0].setType("carrier");
ships[0].setLength(5);
ships[1].setType("battleship");
ships[1].setLength(4);
ships[2].setType("destroyer");
ships[2].setLength(3);
ships[3].setType("submarine");
ships[3].setLength(3);
ships[4].setType("patrol boat");
ships[4].setLength(2);
}
public ShipDerived[] getShips(){
return ships;
}
You initialize this.coordinates twice. First as an inline field initializer and second in the constructor. The statement this.coordinates = getCoordinates(); does not make sense because the getter returns this.coordinates, so you effectively get this.coordinates = this.coordinates;
This shouldn't effect your issue, but my recommendation for easier debugging is to just set all fields that you can to final to avoid issues such as this and remove the superfluous call from the constructor.
Then I would investigate the ArrayListMultimap.create(); method, if there is any way that one returns null.
You have #Override annotation on getCoordinates() so I'm guessing your Ship class also have coordinates field. In shipSunk method you cast your object to Ship class so most likely it operate on field Ship.coordintes whis is null because you are initializing only DerivedShip.coordinates.
Check this for simple example of hiding fields: If you overwrite a field in a subclass of a class, the subclass has two fields with the same name(and different type)?
There are so many strange things in your code:
Why has the Ship class private fields if you don't provide access methods for those fields? Without accessor methods nobody can use those fields, so just delete them!
Why do the ShipDerived constructors initialize the coordinates and c2 fields if you already initialize them at the declaration?
Why does Player.setShips() use some obscure Array.set(ships, a, s); when ships[a] = s; would be sufficient?
Why do your constructors (for Ship, ShipDerived and Player) contain nonsense-code like this.type = type; (in ShipDeriveds default constructor) that seems important but does nothing?
Why does the Player.setShips() method create empty ShipDerived instances and only afterwards sets their values?
After some cleanup your classes could look like:
Ship.java:
import com.google.common.collect.ArrayListMultimap;
public abstract class Ship {
Ship(){
}
abstract void setType(String t);
abstract void setLength(int l);
abstract String getType();
abstract int getLength();
abstract ArrayListMultimap<Integer, Integer> getCoordinates();
abstract void setCoordinates(int i, int j);
}
ShipDerived.java:
import java.util.ArrayList;
import com.google.common.collect.ArrayListMultimap;
public class ShipDerived extends Ship{
private String type;
private int length;
private ArrayListMultimap<Integer, Integer> coordinates = ArrayListMultimap.create();
private ArrayList<Integer> c2 = new ArrayList<>();
public ShipDerived(){
}
public ShipDerived(String t, int l){
this.type = t;
this.length = l;
}
#Override
void setType(String t) {
type = t;
}
#Override
void setLength(int l) {
length = l;
}
#Override
String getType() {
return type;
}
#Override
int getLength() {
return length;
}
#Override
ArrayListMultimap<Integer, Integer> getCoordinates() {
return this.coordinates;
}
ArrayList<Integer> getCoordinatesList() {
return this.c2;
}
#Override
void setCoordinates(int i, int j) {
this.coordinates.put(i, j);
this.c2.add(i);
this.c2.add(j);
}
}
Player.java:
public class Player {
private String name;
private ShipDerived[] ships = new ShipDerived[5];
public Player(){
}
public String getName(){
return name;
}
public void setName(String x){
name = x;
}
public void setShips(){
ships[0] = new ShipDerived("carrier", 5);
ships[1] = new ShipDerived("battleship", 4);
ships[2] = new ShipDerived("destroyer", 3);
ships[3] = new ShipDerived("submarine", 3);
ships[4] = new ShipDerived("patrol boat", 2);
}
public ShipDerived[] getShips(){
return ships;
}
}
These changes might not yet solve your issue, but at least make your code easier to read and understand.
Actually, since the Ship class no longer contains any fields and has only abstract methods you could even turn it into an interface (but that would mean that your methods are now public instead of package private, which would mean that you would also need to declare them as public in ShipDerived).
Ship.java, interface version:
import com.google.common.collect.ArrayListMultimap;
public interface Ship {
void setType(String t);
void setLength(int l);
String getType();
int getLength();
ArrayListMultimap<Integer, Integer> getCoordinates();
void setCoordinates(int i, int j);
}
My two Type classes called SearchType and ResultcodeType need a parent class in an elegant way. How to design these two classes and a parent class both inherit from in an clean and code saving way?
public enum SearchType {
BARCODE(0),
TEXT(1);
SearchType(int i)
{
this.type = i;
}
private int type;
public static SearchType getType(int value) {
for (SearchType searchType : SearchType.values()) {
if (searchType.type == value)
return searchType;
}
throw new IllegalArgumentException("SearchType not found.");
}
public int getNumericType() {
return type;
}
}
and
public enum ResultcodeType {
RESULTS(0),
NO_RESULTS(1),
PROBLEMS(2),
NO_VALUE(-1);
ResultcodeType(int i)
{
this.type = i;
}
private int type;
public static ResultcodeType getType(int value) {
for (ResultcodeType resultcodeType : ResultcodeType.values()) {
if (resultcodeType.type == value)
return resultcodeType;
}
throw new IllegalArgumentException("ResultcodeType not found.");
}
public int getNumericType() {
return type;
}
}
Where do I use SearchType / ResultCodeType?
Layout Data Binding
<ImageView
app:srcCompat="#{item.searchType == SearchType.BARCODE ? #drawable/ic_barcode : #drawable/ic_one_loupe}"
/>
Room database converter class (where there is redundancy again). But for now room can't handle generic types in it's TypeConverter. So this will stay as is.
#TypeConverter
public static SearchType SearchTypeFromInt(Integer value) {
return SearchType.getType(value);
}
#TypeConverter
public static ResultcodeType ResultcodeTypeFromInt(Integer value) {
return ResultcodeType.getType(value);
}
POJO (with room annotation)
#NonNull
#ColumnInfo(name = "resultcode", defaultValue="-1")
private ResultcodeType mResultcode;
Since enums cannot have base classes, I think this is the closest you're going to get:
public interface Typed {
int getNumericType();
static <E extends Enum<E> & Typed> E getType(E[] values, int type) {
for (E value : values)
if (value.getNumericType() == type)
return value;
throw new IllegalArgumentException(values[0].getClass().getSimpleName() +
" not found: " + type);
}
}
public enum SearchType implements Typed {
BARCODE(0),
TEXT(1);
private final int type;
private SearchType(int type) {
this.type = type;
}
#Override
public int getNumericType() {
return this.type;
}
public static SearchType getType(int type) {
return Typed.getType(values(), type);
}
}
public enum ResultcodeType implements Typed {
RESULTS(0),
NO_RESULTS(1),
PROBLEMS(2),
NO_VALUE(-1);
private final int type;
private ResultcodeType(int type) {
this.type = type;
}
#Override
public int getNumericType() {
return this.type;
}
public static ResultcodeType getType(int type) {
return Typed.getType(values(), type);
}
}
Your enums could implement an interface and add default method.
For example:
interface Typed {
Typed getType(int value)
public enum ResultcodeType implements Typed {
public Typed getType(int value) {
for (ResultcodeType resultcodeType :
ResultcodeType.values()) {
if (resultcodeType.type == value)
return resultcodeType;
}
throw new IllegalArgumentException("ResultcodeType not found.");
}
....
}
I also suggest the following approach using a map instead of searching. In fact, all you need is the mapping. You wouldn't even need to supply a value. Note that you can't reference a static value from within a constructor so you have to build the map externally.
enum SearchType {
BARCODE(0), TEXT(1), UNKNOWN(-1);
static Map<Integer, SearchType> map =
Map.of(0, SearchType.BARCODE, 1, SearchType.TEXT);
SearchType(int i) {
this.type = i;
}
private int type;
public static SearchType getType(int value) {
return SearchType.map.getOrDefault(value, SearchType.UNKNOWN);
}
public int getNumericType() {
return type;
}
}
public static void main(String[] args) {
System.out.println(SearchType.getType(0));
System.out.println(SearchType.getType(1));
System.out.println(SearchType.getType(99));
}
I am currently working in Processing 3, and am having troubles understanding the return of a HashMap. I have a map, Map<String, Chromosome> genes = new HashMap<String, Chromosome>() which uses my classes,
class Chromosome{
Genotype geneOne;
Genotype geneTwo;
Chromosome(){ ... }
Chromosome(Genotype gOne, Genotype gTwo){ ... }
void setGeneOne(Genotype gene){ ... }
void setGeneTwo(Genotype gene){ ... }
Genotype getDomGene(){ ... }
Genotype getRecGene(){ ... }
}
class Genotype{
Object value;
float weight;
public Genotype(int value, float weight){ ... }
public Genotype(int[] value, float weight){ ... }
public Genotype(String value, float weight){ ... }
public Genotype(float value, float weight){ ... }
public Object getValue(){ ... }
public float getWeight(){ ... }
public void setValue(int value){ ... }
public void setValue(int[] value){ ... }
public void setValue(String value){ ... }
public void setValue(float value){ ... }
}
What I'm thinking is that when I "get" a value from the map, I should be able to access its methods from there. I.E.
class Flower{
Map<String, Chromosome> genes;
Flower(){
genes = new HashMap<String, Chromosome>();
genes.put("color", new Chromosome(new Genotype(64, 1.0), new Genotype(25,0.5)));
Genotype test = genes.get("color").getDomGene(); //should return the first param passed to the new chromosome
}
}
I'm hoping to avoid having to declare the returned object every time I use it. From all of 20 minutes of googling, I can't seem to find anything about this working, so why does this not work, and what can be done to work around it?
You should just return genOne in getDomGene method.
Chromosome class.
package gen;
class Chromosome {
Genotype geneOne;
Genotype geneTwo;
Chromosome() {
System.out.println("Chromosome.Chromosome");
}
Chromosome(Genotype gOne, Genotype gTwo) {
System.out.println("Chromosome.Chromosome");
}
void setGeneOne(Genotype gene) {
System.out.println("Chromosome.setGeneOne");
}
void setGeneTwo(Genotype gene) {
System.out.println("Chromosome.setGeneTwo");
}
Genotype getDomGene() {
System.out.println("return genOne");
return geneOne;
}
Genotype getRecGene() {
System.out.println("return genTwo");
return geneTwo;
}
}
Genotype class
package gen;
class Genotype {
Object value;
float weight;
public Genotype(int value, float weight) {
System.out.println("Genotype.Genotype");
}
public Genotype(int[] value, float weight) {
System.out.println("Genotype.Genotype");
}
public Genotype(String value, float weight) {
System.out.println("Genotype.Genotype");
}
public Genotype(float value, float weight) {
System.out.println("Genotype.Genotype");
}
public Object getValue() {
System.out.println("Genotype.getValue");
return null;
}
public void setValue(String value) {
System.out.println("Genotype.setValue");
}
public void setValue(float value) {
System.out.println("Genotype.setValue");
}
public void setValue(int value) {
System.out.println("Genotype.setValue");
}
public void setValue(int[] value) {
System.out.println("Genotype.setValue");
}
public float getWeight() {
System.out.println("Genotype.getWeight");
return 0;
}
}
Flower class.
package gen;
import java.util.HashMap;
import java.util.Map;
class Flower {
Map<String, Chromosome> genes;
Flower() {
genes = new HashMap<>();
genes.put("color", new Chromosome(new Genotype(64, 1.0f), new
Genotype(25, 0.5f)));
Genotype test = genes.get("color")
.getDomGene(); //should return the first param passed to the new chromosome
}
public static void main(String[] args) {
new Flower();
}
}
It prints
Genotype.Genotype
Genotype.Genotype
Chromosome.Chromosome
return genOne
return genOne means that you have an access to the geneOne field of Chromosome class, that is its first parameter.
if you put class Flower in a different package? you can't see methods that are not "public". try putting all classes in the same package or make the method public
public Genotype getDomGene(){ ... }
public Genotype getRecGene(){ ... }
I have two classes which pretty much implement the same operations for two different numeric types (except for the getHexadecimalValue() method):
public class IntegerType
{
private int value;
public IntegerType()
{
value = 0;
}
public void setValue(int value)
{
this.value = value;
}
public int getValue()
{
return value;
}
public String getHexadecimalValue()
{
int integerValue = (int) getValue();
String hexadecimal = ValueConversions.toHexadecimal(integerValue);
return hexadecimal;
}
}
and
public class FloatingPointType
{
private float value;
public FloatingPointType()
{
value = 0;
}
public void setValue(float value)
{
this.value = value;
}
public float getValue()
{
return value;
}
public String getHexadecimalValue()
{
float floatingValue = (float) getValue();
int intBits = Float.floatToRawIntBits(floatingValue);
return ValueConversions.toHexadecimal(intBits);
}
}
I'm wondering what the best way would be to reduce this redundancy by e.g. defining a superclass called NumberType like this:
public abstract class NumberType
{
protected Number value;
public NumberType()
{
setValue(0);
}
public void setValue(Number value)
{
this.value = value;
}
public Number getValue()
{
return value;
}
public abstract String getHexadecimalValue();
}
Now the problem is that any number can be passed to my inheriting classes but I only want to accept ints and floats respectively while still keeping redundancy to a minimum:
public class IntegerType extends NumberType
{
#Override
public String getHexadecimalValue()
{
// Crashes on runtime if the value doesn't happen to be of the expected type
int integerValue = (int) getValue();
String hexadecimal = ValueConversions.toHexadecimal(integerValue);
return hexadecimal;
}
}
Can this be done by still keeping proper type checking?
You can try this way.
public abstract class NumberType<T extends Number> {
protected T value;
public NumberType(T value) {
this.value = value;
}
public void setValue(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public abstract String getHexadecimalValue();
}
public class FloatingPointType extends NumberType<Float> {
public FloatingPointType() {
super(0f);
}
public String getHexadecimalValue() {
return ValueConversions.toHexadecimal(Float.floatToRawIntBits(value));
}
}
Note: Float and Integer, both class has static toHexString methods which you can directly use if you are comfortable to use them.
public static String toHexString(float f)
public static String toHexString(int i)
This can be done with overloading
for example:
public abstract class NumberType
{
private Number value;
public NumberType()
{
setValue(0);
}
public void setValue(float value)
{
this.value = value;
}
public void setValue(int value)
{
this.value = value;
}
public Number getValue()
{
return value;
}
public abstract String getHexadecimalValue();
}
You can also add then:
public int getIntValue()
{
return value.intValue();
}
public float getFloatValue()
{
return value.floatValue();
}
Ideally, setValue(Number value) must not allow entering any value but float in FloatingPointType and setValue(Number value) must not allow entering any value but int in IntegerType. You can check by using intValue() and floatValue() methods in class Number and throw exception if inappropriate value entered. Number class methods
It would be something like this in setValue(Number value) of IntegerType
if(value.intValue()!= value)
throw new IllegalArgumentException()
I have a class called x which is a array list and needs to be sorted in Decreasing order by Value.
My Class-
public static class x
{
public int id;
public double value;
public x(int _id, double _value)
{
id = _id;
value = _value;
//System.out.println(Integer.toString(id));
}
public Integer getID(){
return id;
}
public double getValue(){
return value;
}
//Sorting
public static Comparator<x> getComparator(SortParameter... sortParameters) {
return new xComparator(sortParameters);
}
public enum SortParameter {
VAL_DESCENDING
}
private static class xComparator implements Comparator<x> {
private SortParameter[] parameters;
private xComparator(SortParameter[] parameters) {
this.parameters = parameters;
}
public int compare(x o1, x o2) {
int comparison;
for (SortParameter parameter : parameters) {
switch (parameter) {
case VAL_DESCENDING:
comparison = o2.id - o1.id;
if (comparison != 0) return comparison;
break;
}
}
return 0;
}
}
}
I Call it like:
cp = x.getComparator(x.SortParameter.VAL_DESCENDING);
Collections.sort(attr1, cp);
attr1 is my array list
Just for Reference I am following this
I am getting error:
cannot find symbol : variable cp
I am a newbie to java :(
try using Comparator<x> cp = x.getComparator(x.SortParameter.VAL_DESCENDING); to declare it. you can not use a variable until it is declared