getClass() not working? - java

public int compareTo(Object a) {
int Output = 0;
if(this.equals(a))
Output = 0;
if(a instanceof this.getClass()) {
if(this._numDec > ((this.getClass())a)._numDec)
Output = 1;
if(this._numDec < ((this.getClass())a)._numDec)
Output = -1;
}
return Output;
}
Hello. My CS instructor told our class to create a function that would determine which of the two values would be larger, outputting 1 if the former is larger, 0 if they are equal, and -1 if the former is smaller. The this.getClass() was originally a Hexadecimal class for converting Hexadecimal values into _numDec. However, I get errors when I try to use this.getClass(). Can somebody help?

Write out the exact class name explicitly.
if (a instanceof Hexadecimal) {
if (this._numDec > ((Hexadecimal) a)._numDec)
Output = 1;
if (this._numDec < ((Hexadecimal) a)._numDec)
Output = -1;
}
By the way, if a is not a Hexadecimal object then your method is going to return 0. It should return non-zero.

You are not having problems because your call to getClass() isn't working, you are having problems because you are using incorrect casting syntax. The correct syntax is of the form:
<type> target_var = (<type>) source_var;
Where <type> is expected to be an actual Java type (primitive or object). Valid Java primitive types are (int, float, long, double, char, boolean ...). Valid object types are specified by their fully qualified name, or simple name if the type is imported. For example (String, Serializable, Object, JFrame ...).
In your code, this line:
if(this._numDec > ((this.getClass())a)._numDec)
Will not compile because you are specifying the casting to be this.getClass(), which is a dynamic expression, not a valid type.
There are several ways to accomplish your real goal, which is too determine if the supplied object is of a type that you can compare to the current object, and then to perform the comparison. Here's one such way:
if(a instanceof Binary)) {
if(this.getNumDec() > ((Binary)a).getNumDec())
Output = 1;
else
Output = -1;
} else if(a instanceof Hexadecimal) {
if(this.getNumDec() > ((Hexadecimal)a).getNumDec())
Output = 1;
else
Output = -1;
}
Note that I have replaced the use of direct property access with accessor methods.

Related

Java, how to read multiple data types from one function input?

let's say I want to call a function in my code and I want to input an integer in one case and in another case a string/boolean/char... I know var is used for doing this but it doesn't work in my code.
what do I need to change/add for it work and be able to receive different data types?
public static void add(var num){//-here is var but I get an error
//do something
}
I know var is used for doing this but it doesn't work in my code.
No, it is not.
Java is strongly and simply typed. Things have a type. There is no dynamic/ducktyping type. var is not that. var is just syntax sugar.
In a ducktyping/dynamic language, you could write:
var x;
x = 5;
x = "Hello";
In java, you cannot do that. var x; is a compiler error.
var x in java is just shorthand for: Take the type of the thing you are assigning to x on this very line. Assume I meant that write that type out. In other words, var is allowed only if you inline initialize:
var x = "Hello"; // legal; and 100% the same as writing String x = "Hello"
x = 5; // compiler error. x is of type String, and 5 isn't a string.
what do I need to change/add for it work and be able to receive different data types?
What is the common type amongst String, boolean, char, and int?
Object is the best available answer, and it's not a great one. So that's what you'd have to do:
public static void add(Object num) {
if (num instanceof Number) { .... }
else if (num instanceof String) { .... }
else if (num instanceof Boolean) { .... }
else throw new IllegalArgumentException("Only numbers, strings, and booleans allowed");
}
But this is extremely non-java. It sounds like you want to design a weakly typed system, where "5" and 5 are treated the same, and true and 1 are treated the same. I suggest you don't do that.
An alternative is to just make that many methods. In java, a method is defined by its entire signature: The name, but also the param types and return types, as well as the type the method is in. So, you can make more than one add method:
public static void add(String num) { ... }
public static void add(int num) { ... }

How to override Java's restrictions for objects

I am given an instance of the object class (String, int, double, or boolean) from a database. I need to write a method that can compare this object to something else (String, int, double, or boolean) using binary operators (e.g. <=, !=, >, etc.). I will only run this method if the two objects are of the same type. My method looks like
public boolean comparison(Object a, Object b, String operator) {
int result = a.compareTo(b);
String a2 = a.getClass().getName();
//followed by if/else if blocks to return true or false
//depending on operator and result
}
I have designed the if/else if blocks to ensure that no binary operator will be used for incompatible types (e.g. >= for a String object). The problem is that I get a "can't find symbol error" when I try to compile because the object class doesn't have a compareTo() method. If this was python, there wouldn't actually be any issue because I would never be putting anything into the comparison function that didn't have a compareTo() method. However, because of java's formatting I'm forced to declare the input as 'Object' because I can't say specifically what type of object I have to compare at a given moment.
Is there some way I could override Java's restrictions and force it to trust me that Object a will always have a compareTo() method? Because right now, it seems like I'm going to have to downcast the objects into Strings, ints, doubles, or booleans, and then write 4 different new comparison functions for each data type.
Since the compareTo method is declared in the java.lang.Comparable<T> interface, the usage of Bounded Type Parameters can constrain your a and b arguments in order to accept only objects which implement the interface itself.
You can check the operator parameter in order to affect the boolean result.
If you wish, the usage of an enum value helps to avoid string mismatching.
For brevity, the code below doesn't take in account null values.
enum Operator {
GREATER_OR_EQUALS,
LESS_OR_EQUALS
}
public <T extends Comparable<T>> boolean comparison(T a, T b, Operator operator) {
int test = a.compareTo(b);
switch(operator) {
case GREATER_OR_EQUALS:
return test >= 0;
default:
return test <= 0;
}
}
The Java way is to first use the instanceof operator to then cast to an appropriate class:
if (a instanceof String && b instanceof String) {
String aAsString = (String) a;
int comparisonResult = a.compareTo(b);
compareTo() gives you a negative result if a < b, 0 when a == b and a positive result if a > b. So alone that int result tells you enough to decide what your potential comparison operations should result in. The numeric types int/Integer, ... have similar methods.
Of course this only works if your assumptions are really correct and the object is really a String or Boolean. And please note that boolean and Boolean are two somehow different types!
Casting variables in Java
The top answer summarizes what I wanted to do. The code successfully compiled when I said
int result;
if (a instanceof Comparable && b instanceof Comparable) {
result = ((Comparable) a).compareTo((Comparable) b);
}
I haven't tested it, but fantaghirocco's solution also seems like it could work.

NosuchMethodException when I try to create an object using reflexion [duplicate]

I have a method in my test framework that creates an instance of a class, depending on the parameters passed in:
public void test(Object... constructorArgs) throws Exception {
Constructor<T> con;
if (constructorArgs.length > 0) {
Class<?>[] parameterTypes = new Class<?>[constructorArgs.length];
for (int i = 0; i < constructorArgs.length; i++) {
parameterTypes[i] = constructorArgs[i].getClass();
}
con = clazz.getConstructor(parameterTypes);
} else {
con = clazz.getConstructor();
}
}
The problem is, this doesn't work if the constructor has primitive types, as follows:
public Range(String name, int lowerBound, int upperBound) { ... }
.test("a", 1, 3);
Results in:
java.lang.NoSuchMethodException: Range.<init>(java.lang.String, java.lang.Integer, java.lang.Integer)
The primitive ints are auto-boxed in to object versions, but how do I get them back for calling the constructor?
Use Integer.TYPE instead of Integer.class.
As per the Javadocs, this is "The Class instance representing the primitive type int."
You can also use int.class. It's a shortcut for Integer.TYPE. Not only classes, even for primitive types you can say type.class in Java.
To reference primitive types use, for example:
Integer.TYPE;
You will need to know which arguments passed into your method are primitive values. You can do this with:
object.getClass().isPrimitive()
Since the primitive types are autoboxed, the getConstructor(java.lang.Class<?>... parameterTypes) call will fail. You will need to manually loop through the available constructors. If all types match then you're fine. If some types do not match, but the required type is a primitive AND the available type is the corresponding wrapper class, then you can use that constructor. See bellow:
static <C> Constructor<C> getAppropriateConstructor(Class<C> c, Object[] initArgs){
if(initArgs == null)
initArgs = new Object[0];
for(Constructor con : c.getDeclaredConstructors()){
Class[] types = con.getParameterTypes();
if(types.length!=initArgs.length)
continue;
boolean match = true;
for(int i = 0; i < types.length; i++){
Class need = types[i], got = initArgs[i].getClass();
if(!need.isAssignableFrom(got)){
if(need.isPrimitive()){
match = (int.class.equals(need) && Integer.class.equals(got))
|| (long.class.equals(need) && Long.class.equals(got))
|| (char.class.equals(need) && Character.class.equals(got))
|| (short.class.equals(need) && Short.class.equals(got))
|| (boolean.class.equals(need) && Boolean.class.equals(got))
|| (byte.class.equals(need) && Byte.class.equals(got));
}else{
match = false;
}
}
if(!match)
break;
}
if(match)
return con;
}
throw new IllegalArgumentException("Cannot find an appropriate constructor for class " + c + " and arguments " + Arrays.toString(initArgs));
}
you can write
int[].class.getComponentType()
or
Integer.TYPE
or
int.class
If primitive int value is autoboxed into Integer object, it's not primitive anymore. You can't tell from Integer instance whether it was int at some point.
I would suggest passing two arrays into test method: one with types and another with values. It'll also remove ambiguity if you have a constructor MyClass(Object) and pass string value (getConstructor would be looking for String constructor).
Also, you can't tell expected parameter type if parameter value is null.
To actually check if a type is a primitive or it's wrapper use:
ClassUtils.isPrimitiveOrWrapper(memberClazz)
In the case you want to check if it's a specific type take a look at this:
https://stackoverflow.com/a/27400967/2739334
In any case #Andrzej Doyle was completely right!

Java CompareTo method states I cannot convert int to boolean even though neither is used

public int compareTo(Person p) {
int res = 1;
String personStr = p.getId();
String thisId = this.getId();
if(thisId.equals(personStr)){
res = 0;
}
else if(thisId.compareTo(personStr)){
res = -1;
}
return res;
}
A quite simple compareTo method I have implemented but I don't get the error message. The condition in the else if statemint gives me a message saying that it can't convert from int to boolean. I get that, but the thing is that I'm using netiher. I just want to compare 2 simple strings, why does this happen?
What you should notice is that the interface 'compareTo' is returning an int 'public int compareTo' being the sign
if statements rely on a boolean value, however you use thisId.compareTo(personStr) which will return an integer, just like the method you are creating.
Your first if statement is fine - 'equals' returns a boolean. However the second does not, it will likely return either a -1, a 0 or a 1.
but the thing is that I'm using netiher
Are you sure about that?
This results in an int:
thisId.compareTo(personStr)
But you're using it as a Boolean:
if (yourResult)
An if statement requires a boolean, it can't just be used on any value. For example, consider the difference between this:
if (value == 1)
and this:
if (value)
In some languages you can get away with that. Some languages assign degrees of "truthiness" to all types, allowing you to use them in boolean expressions. Java is not one of them. You have to explicitly define your boolean logic in Java:
if(thisId.compareTo(personStr) > 0) // or whatever your logic should be
if you just want to compare those 2 strings why not use
public int compareTo(Person p) {
String personStr = p.getId();
String thisId = this.getId();
return thisId.compareTo(personStr);
}

comparison of String and Integer using compareTo and instanceOf

I have a code snippet which I am not able to understand what exactly it does..
This code is in JavaBean..
private Object myNumb;
//then getter and setter for this
public int compareTo(myRptObj o){
if (myNumb instanceof String && o.myNumb instanceof Integer) {
return_value = 1;
} else if (myNumb instanceof Integer && o.myNumb instanceof String) {
return_value = -1;
} else if (myNumb instanceof String && o.myNumb instanceof String) {
return_value = ((String) myNumb).compareTo((String)o.myNumb);
} else if (myNumb instanceof Integer && o.myNumb instanceof Integer) {
return_value = ((Integer) myNumb).compareTo((Integer)o.myNumb);
}
}
I want to understand compareTo and how the comparison for String and Integer is done?
myNumb can be of type Integer or String.
The snippet makes sure that any Integer compares less than any String.
Integer-Integer and String-String comparisons are done the way you'd expect.
the first two if clauses ensure that Strings are considered greater than integers. The second two if clauses delegate the comparison between Strings and between Integers to the compareTo() implementation of these classes so that they are ordered as usual.
Note that it is very, very bad design to have this kind of code where a variable can be "of type X or Y" - exactly because it forces you to write code like this.
Instead, decide on one type and convert to/from that type where necessary.
... what exactly it does.
Basically: strings are greater than integers, if both are the same type use their natural ordering (either compare 2 strings or 2 integers).
Since myNumb can be either a String or an Integer, compareTo is checking what types they are first. If they are not the same type (one is an Integer and one is a String) they are not equal and therefore returns 1 or -1 as appropriate. If they are of the same type, it is casting them to that type and delegating to that type's compareTo.

Categories

Resources