How can I program my class to accept both Integers and Floats, I suppose I'll need to use generics, am I correct?
public class Vec2 {
private int x, y;
public Vec2(int xa, int ya) {
this.x = xa;
this.y = ya;
}
public Vec2() {
this(0, 0);
}
public Vec2(Vec2 vec) {
this(vec.x, vec.y);
}
public void addX(int xa) {
x+=xa; // I get an exception here when I try to use generics.
}
public void addY(int ya) {
y+=ya; // I get an exception here when I try to use generics.
}
Any ideas how to program my class to accept floats, integers and doubles altogether?
For the time being, we cannot have generics over primitives like int or double, so you will be forced to use boxed representations. It really is easier to just make a separate class for int and double. But if you want to use generics, here's how you can do it in a type-safe way (using java8):
public class Vec2<T> {
private final BinaryOperator<T> adder;
private T x, y;
private Vec2(BinaryOperator<T> adder, T x, T y) {
this.adder = adder;
this.x = x;
this.y = y;
}
public void addX(T xa) {
x = adder.apply(x, xa);
}
public void addY(T ya) {
y = adder.apply(y, ya);
}
public static Vec2<Integer> ofInt(Integer x, Integer y) {
return new Vec2<>(Integer::sum, x, y);
}
public static Vec2<Double> ofDouble(Double x, Double y) {
return new Vec2<>(Double::sum, x, y);
}
}
Vec2<Integer> intvec = Vec2.ofInt(5, 3);
intvec.addX(8);
Vec2<Double> dblvec = Vec2.ofDouble(5.2, 8.9);
dblvec.addY(-.9);
You could use BigDecimal to back your Vec2 and then you could use create addX and addY method(s) for long and double fairly easily. Something like,
public class Vec2 {
private BigDecimal x, y;
public Vec2(double xa, double ya) {
this.x = BigDecimal.valueOf(xa);
this.y = BigDecimal.valueOf(ya);
}
public Vec2(long xa, long ya) {
this.x = BigDecimal.valueOf(xa);
this.y = BigDecimal.valueOf(ya);
}
public Vec2(Vec2 vec) {
this.x = vec.x;
this.y = vec.y;
}
public void addX(double xa) {
x = x.add(BigDecimal.valueOf(xa));
}
public void addX(long xa) {
x = x.add(BigDecimal.valueOf(xa));
}
public void addY(double ya) {
y = y.add(BigDecimal.valueOf(ya));
}
public void addY(long ya) {
y = y.add(BigDecimal.valueOf(ya));
}
#Override
public String toString() {
return String.format("x = %s, y = %s", x.toString(), y.toString());
}
}
No, you don't, merely have your class inherit from Number and use type checking to ensure that values are of the appropriate class, if necessary, e.g.
Class IsraelG99sClass {
Number n;
public Number add(Number n2) {
if (n instanceof Integer && n2 instanceof Integer) {
return new Integer(n.intValue() + n2.intValue());
} else {
return new Double(n.doubleValue() + n2.doubleValue());
}
}
public Number getValue() {
if ((n instanceof Integer) || (n instanceof Float)) {
return n;
} // handle the other case as appropriate
}
}
Floats and ints are very different values with vastly different mins and maxes. I would try using doubles as the data member with overloaded constructors for different variable types instead of generics unless generics are really needed.
Yes, you can use generics and make your x and y attributes of type T.
But you won't be able to just implement the addX and addY in they way you want.
Check these other answers on how to implement a generic number addition, it's not as simple but you should be able to do it that way.
Java Generics and adding numbers together
how to write a generic method for adding numbers
First of all, I'm operating under the assumption that you want x and y to be of varying (generic) type.
For this, you would want:
public class Vec2<E extends Number> {
private E x, y;
public Vec2(E xa, E ya) {
this.x = xa;
this.y = ya;
}
//Not _easily_ possible with generics, as the compiler has no guarantee that
//zero is an acceptable value. Consider some variation of a Factory pattern,
//but this will work. Note that there is an "officially"-unchecked cast warning.
public Vec2() {
super();
final Number zero = 0.0;
this.x = (E)zero;
this.y = (E)zero;
}
public Vec2(Vec2<E> vec) {
this(vec.x, vec.y);
}
public void addX(E xa) {
Number c = x.doubleValue() + xa.doubleValue();
x = (E)c;
}
public void addY(E ya) {
Number c = y.doubleValue() + ya.doubleValue();
x = (E)c;
}
This should work well. While I encourage you to use generics, note that keeping a numeric type (like int, float, or double) as a generic is often not advisable, as they're only similar on the surface. When you dig into the operations of, say, "+", they are radically different dependent on type. You will also have an assortment of unchecked-cast warnings in this code; perhaps I could have rooted them out properly had I the time, but this just goes back to my warning about generic numbers.
You will also notice a few flukes of the language doing this, such as the way that (E)zero works, but (E)(0.0) does not.
By and large, though, generics are a much easier and cleaner way to go about things than inheritance, when it is possible.
Related
Here when I run this below code I get called as the output and I was wondering why not called new. Since 1 comes under both short and int range.
public class MyClass {
private int x;
public MyClass(){
this(1);
}
public MyClass(int x){
System.out.println("called");
this.x = x;
}
public MyClass(short y){
System.out.println("called new");
this.x = y;
}
public static void main(String args[]) {
MyClass m = new MyClass();
System.out.println("hello");
}
}
1 is an int literal, so MyClass(int x) is chosen.
Even if you remove the MyClass(int x) constructor, MyClass(short y) won't be chosen. You'll get a compilation error instead, since 1 is not short.
You'll have to cast 1 to short - this((short)1); - in order for the MyClass(short y) to be chosen.
As an addition to others answer I can suggest you to check which constructors are being called when you initialize variables of other types using the same literal:
short s = 1;
int i = 1;
And then check which constructor of MyClass is being called as you call them with above arguments.
i start learn java and i have a little problem:
I have a class Point:
public class Point {
int x;
int y;
void setX(Point point){
x=point.x;
}
void setY(Point point){
y=point.y;
}
}
Now i have a task:
" change method setX() and setY() that these methods return previous values of x and y. "
Can You help me with understanding of this task? Totally dont get it.
You'd have to change from void to int return type(s) and then store the old value to return after you set it. Something like,
int setX(Point point) {
int old = this.x;
this.x = point.x;
return old;
}
int setY(Point point) {
int old = this.y;
this.y = point.y;
return old;
}
or you might perform the assignment in a finally block, and return the value in a try like
int setX(Point point) {
try {
return this.x;
} finally {
this.x = point.x;
}
}
I have been instructed to "Write a class, Triangle, with one instance variable that takes two string values, (filled or not filled)".
I'm new to Java, and still haven't come across a situation where you could have two potential values for one instance variable.
How would I do this?
main method was given:
public static void main(String[] args)
{
TwoDPolygon polygons[] = new TwoDPolygon[3];
polygons[0] = new Triangle("filled", 8.5, 12.0);
polygons[1] = new Triangle("not Filled", 6.5, 7.5);
polygons[2] = new Triangle(7.0);
for (int i=0; i<polygons.length; i++)
{
System.out.println("Object is " + polygons[i].getName());
System.out.println("Triangle " + polygons[i].getStatus());
System.out.println("Area is " + polygons[i].area());
}
}
Ok I have redesigned the code based on your updated question.
First of all, you need an abstract class called TwoDPolygon. This class is an abstract representation of all your polygons. It contains the constructors and the methods you need.
abstract class TwoDPolygon {
protected String filled;
protected double x;
protected double y;
protected TwoDPolygon(String filled, double x, double y){
this.filled=filled;
this.x=x;
this.y=y;
}
protected TwoDPolygon(double x, double y){
this.x=x;
this.y=y;
}
protected TwoDPolygon(double y){
this.y=y;
}
abstract String getName();
abstract String getStatus();
abstract Double area();
}
Then the next step is to create the Triangle class. You will have to extend the abstract TwoDPolygon. This is the code:
public class Triangle extends TwoDPolygon {
//the first constructor
public Triangle(String filled, double x, double y) {
super(filled, x, y);
}
//the second one
public Triangle(double x, double y){
super(x,y);
}
//the third one
public Triangle(double y){
super(y);
}
public String getName() {
return "Triangle";
}
public String getStatus() {
return filled;
}
public Double area() {
//Insert code here which calculates the area
return 0.0;
}
}
This is all. Every time when you instantiate a Triangle polygon it will chose the right constructor based on the parameters you supply. Now when you run your main you will have the following output:
Object is Triangle
Triangle filled
Area is 0.0
Object is Triangle
Triangle not Filled
Area is 0.0
Object is Triangle
Triangle null
Area is 0.0
Note: The area's code is not done. You will have to do that but I guess that shouldn't be a problem.
Also I have created three constructors as you said, but I don't know the parameters of the third one. I just guessed that it has only the x and y value.
I hope this is what you're looking for!! It shouldn't be that hard to adapt to your specific requirements, as I think it looks almost done.
It is most likely meant that it takes one argument with 2 valid values:
class Triangle {
Triangle(String val) {
if (!"filled".equals(val) || !"not filled".equals(val))
throw ...;
}
}
or enum type
public enum Type {
FILLED,
NOT)FILLED
}
I think what is meant is you have one boolean instance variable named isFilled.
then you could have something like this:
boolean isFilled;
public triangle(String filled, int x, int y) {
if (filled == "filled") {
isFilled = true;
} else if (filled == "notFilled") {
isFilled = false;
} else {
//handle exception or whatever
}
}
That way you can have one instance variable but still use a string in the constructor. I don't think this is a very practical thing to do but if that is what your assignment said then that is a good way to do it. I hope I helped!
Let me give some code so you can see what I'm doing with the following java code for android. Say for example I have the following two classes, one extended from the other:
class MyClassOne {
protected float x, y;
MyClassOne(float x, float y) {
this.x = x; this.y=y;
}
public void printY(){
System.out.print(y);
}
}
class MyClassTwo extends MyClassOne {
protected String stringSpecificToThisClass;
private long longSpecificTothisClass;
MyClassTwo(float x, float y, String s, long l) {
this.x=x; this.y=y;
this.longSpecificTothisClass= l; this.stringSpecificTothisClass=s;
}
}
These classes are then initialized in the following way
private ArrayList<MyClassOne> mClassOne = new ArrayList<MyClassOne>();
private ArrayList<MyClassTwo> mClassTwo = new ArrayList<MyClassTwo>();
for(int i=0;i<5;i++){
Random random = new Random(10);
mClassOne.add(new MyClassOne(i*12, random.nextInt()));
mClassTwo.add(new MyClassOne(i*11, random.nextInt()));
}
now, what I want to do is compare and sort both arraylists according to the value of y.
The way i do this for a single list is like so:
private Object[][] mSort(){
Object[][] mSort = new Object[mClassOne.size()][2];
for(int i = 0; i<mClassOne.size(); i++){
mSort[i][0] = i;
mSort[i][1] = mClassOne.get(i).y;
}
Arrays.sort(mSort, new Comparator<Object[]>(){
#Override
public int compare(Object[] obj1, Object[] obj2){
Float comp1 = (Float)obj1[1]; Float comp2 = (Float) obj2[1];
return comp1.compareTo(comp2);
}
});
return mSort;
}
Object[][] mSort = mSort();
for(int i=0;i<mClassOne.size();i++){
int z = (Integer)mSort[i][0];
mClassOne.get(z).printY();
}
which could output something like this:
2, 4, 5, 6, 9
Hopefully the code above is clear enough so others can see what I'm trying to do; the question is:
"How could I combine both ArrayLists then sort them by their respective y value."
The Answer I was looking for
ArrayList<MyClassOne> mTest = new ArrayList<MyClassOne>();
mTest.addAll(mClassOne);
mTest.addAll(mClassTwo);
Collections.sort(mTest, new Comparator<MyClassOne>(){
#Override
public int compare(MyClassOne obj1, MyClassTwo obj2) {
return (int) (obj1.getY() - obj2.getY()); }
}
);
// mTest is now sorted, verified by ~ foreach(mTest) {print mTest.getY(); }
Well, you could use a Comparator<MyClassOne> which should be able to handle MyClassTwo instances as well, since MyClassTwo extends MyClassOne.
Just create a single List<MyClassOne>, add all elements of the other lists and sort.
In cases where the classes don't extend each other, introduce a common interface.
I want to declare a List<int[]> or Map<int[],Boolean> but it's very difficult because arrays in Java doesn't implement the equals() method. If two arrays a and b are equal, a.equals(b) returns false.
Although java.util.Arrays.equals() compares arrays for equality, how do I get a List to use that method for comparison instead of the screwed-up equals()?
By the way, the int[] is a array [x,y,z] describing a coordinate. I want to put a bunch of these coordinates into a List or Map.
Why not declare your own class for a point? e.g.
class Point3D {
int x, y, z;
public boolean equals() {
// logic
}
}
and then declare List<Point3D>.
A general solution is to wrap the array in a method that does implement equals (and hashCode and perhaps compare, possibly toString and other methods that might make sense) as you wish:
public final class IntArrayWrapper {
private final IntArrayWrapper[] values;
public IntArrayWrapper(int... values) {
if (values == null) {
throw new NullPointerException();
}
this.values = values;
}
#Override public boolean equals(Object obj) {
if (!(obj instanceof IntArrayWrapper)) {
return false;
}
IntArrayWrapper other = (IntArrayWrapper)obj;
return java.util.Arrays.equals(this.values, other.values);
}
#Override public int hashCode() {
return java.util.Arrays.hashCode(values);
}
public int[] getValues() {
return values;
}
[...]
}
In this specific case, using arrays to contain certain fixed data values is poor design. Do it properly:
public final class Point {
private final int x;
private final int y;
private final int z;
public static Point of(int x, int y, int z) {
return new Point(x, y, z);
}
private Point(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
#Override public boolean equals(Object obj) {
if (!(obj instanceof Point)) {
return false;
}
Point other = (Point)obj;
return
this.x == other.x &&
this.y == other.y &&
this.z == other.z;
}
#Override public int hashCode() {
int hash;
hash = x;
hash = hash*41+y;
hash = hash*41+z;
return hash;
}
[...]
}
First of all, this isn't legal syntax. List can only take a single generic type.
Second, I would say that if you're worried about doing things at this low a level you aren't thinking abstractly enough. An array of arrays or a List of Lists is common enough. People who create matrix classes for linear algebra use them all the time. But you leverage objects and Java best when you hide those implementation details from clients of your class. Try it for your case and see if it helps.
You could always use the existing Point3d class instead of an array.
edit: The Apache Commons Math library also has some good options.