How can I see in Java if an Object is an array without using reflection?
And how can I iterate through all items without using reflection?
I use Google GWT so I am not allowed to use reflection :(
I would love to implement the following methods without using refelection:
private boolean isArray(final Object obj) {
//??..
}
private String toString(final Object arrayObject) {
//??..
}
BTW: neither do I want to use JavaScript such that I can use it in non-GWT environments.
You can use Class.isArray()
public static boolean isArray(Object obj)
{
return obj!=null && obj.getClass().isArray();
}
This works for both object and primitive type arrays.
For toString take a look at Arrays.toString. You'll have to check the array type and call the appropriate toString method.
You can use instanceof.
JLS 15.20.2 Type Comparison Operator instanceof
RelationalExpression:
RelationalExpression instanceof ReferenceType
At run time, the result of the instanceof operator is true if the value of the RelationalExpression is not null and the reference could be cast to the ReferenceType without raising a ClassCastException. Otherwise the result is false.
That means you can do something like this:
Object o = new int[] { 1,2 };
System.out.println(o instanceof int[]); // prints "true"
You'd have to check if the object is an instanceof boolean[], byte[], short[], char[], int[], long[], float[], double[], or Object[], if you want to detect all array types.
Also, an int[][] is an instanceof Object[], so depending on how you want to handle nested arrays, it can get complicated.
For the toString, java.util.Arrays has a toString(int[]) and other overloads you can use. It also has deepToString(Object[]) for nested arrays.
public String toString(Object arr) {
if (arr instanceof int[]) {
return Arrays.toString((int[]) arr);
} else //...
}
It's going to be very repetitive (but even java.util.Arrays is very repetitive), but that's the way it is in Java with arrays.
See also
Managing highly repetitive code and documentation in Java
Java Arrays.equals() returns false for two dimensional arrays.
One can access each element of an array separately using the following code:
Object o=...;
if ( o.getClass().isArray() ) {
for(int i=0; i<Array.getLength(o); i++){
System.out.println(Array.get(o, i));
}
}
Notice that it is unnecessary to know what kind of underlying array it is, as this will work for any array.
There is no subtyping relationship between arrays of primitive type, or between an array of a primitive type and array of a reference type. See JLS 4.10.3.
Therefore, the following is incorrect as a test to see if obj is an array of any kind:
// INCORRECT!
public boolean isArray(final Object obj) {
return obj instanceof Object[];
}
Specifically, it doesn't work if obj is 1-D array of primitives. (It does work for primitive arrays with higher dimensions though, because all array types are subtypes of Object. But it is moot in this case.)
I use Google GWT so I am not allowed to use reflection :(
The best solution (to the isArray array part of the question) depends on what counts as "using reflection".
In GWT, calling obj.getClass().isArray() does not count as using reflection1, so that is the best solution.
Otherwise, the best way of figuring out whether an object has an array type is to use a sequence of instanceof expressions.
public boolean isArray(final Object obj) {
return obj instanceof Object[] || obj instanceof boolean[] ||
obj instanceof byte[] || obj instanceof short[] ||
obj instanceof char[] || obj instanceof int[] ||
obj instanceof long[] || obj instanceof float[] ||
obj instanceof double[];
}
You could also try messing around with the name of the object's class as follows, but the call to obj.getClass() is bordering on reflection.
public boolean isArray(final Object obj) {
return obj.getClass().toString().charAt(0) == '[';
}
1 - More precisely, the Class.isArray method is listed as supported by GWT in this page.
You can create a utility class to check if the class represents any Collection, Map or Array
public static boolean isCollection(Class<?> rawPropertyType) {
return Collection.class.isAssignableFrom(rawPropertyType) ||
Map.class.isAssignableFrom(rawPropertyType) ||
rawPropertyType.isArray();
}
Simply obj instanceof Object[] (tested on JShell).
Related
I'm triying to make a function to validate if an object is inside a List of objects, but I have a problem, because I'm using a class to define the properties of the awaiting object, so in the IDE seems to give some help to solve the issue, but I don't want to do like that, my idea, is to make a function global, to validate any type of list, so this is my code, sorry if are not good, but is a try.
*The list and the object have the same class.
objExist(statusClaim, statusClaimRP) /*<=== Is just the function on my code for reference */
private Boolean objExist(List<Object> arreglo, Object objeto) throws JSONException {
Integer valida = 0;
for(Integer i = 0; i < arreglo.size(); i++) {
if(arreglo.get(i) == objeto) {
valida++;
}
}
if(valida > 0) {
return false;
} else {
return true;
}
}
The method objExist(List'<'Object'>', Object) in the type ClaimService is not applicable for the arguments (List'<'StatusClaimDTO'>', StatusClaimDTO).
As I understood you want to make sure that certain list contains certain object?
If so you can use list.contains(objectToFind) or streams:
listOfSomeObjects.stream().anyMatch(obj -> obj.equals(objectToFind);
Alternatevely, for learning purposes, you can simply iterate over you list in for loop and wrap it into generic method:
private <T> boolean listContainsElement(List<T> list, T elementToFind) {
for (T element: list) {
if (element.equals(elementToFind)) {
return true;
}
}
return false;
}
But it's not practical.
Note: == compares references, not objects themselves, which means if obj1 == obj2 that both variable point to the same instance of the object, if this is what you want then ok. But ussually objects are compared with equals method which you can override and use your own logic, otherwise it has default implementation that basically acts like == operator.
This is what I wrote.
public class Test {
public static void main(String[] args) {
Object a1 = new A();
Object a2 = new Object();
System.out.println(a1.toString());
System.out.println((a1 == a2) + " " + (a1.equals(a2)));
}
}
class A {
int x;
public boolean equals(Object obj) {
A _obj = (A) obj;
return x == _obj.x;
}
public String toString() {
return "A's x is " + x;
}
}
How can I make 'false true' on the console? Except revising the main method. Revise only A method.
I tried to make change the Object a2 to an a2. How Can I change that in the A class?
The reason you're getting the error class java.lang.Object cannot be cast to class A is because the object you're comparing it to is not an instance of class A, so trying to cast the object as such will fail.
When implementing the .equals method, you should always perform these three checks first to ensure the safety of the object before you try comparing its properties:
if (obj == this) return true; If the two objects are the exact same object, meaning that they are the same instance, not just two objects with the same properties, immediately return true because there is no need to check the properties.
if (obj == null) return false; This prevents a NullPointerException by trying to access a property of a null object (such as when in your code you do return x == _obj.x)
if (!(obj instanceof A)) return false; If the object is not an instance of your class, the typecast will fail (as it did in your code) and this protects against that by returning false before trying to cast.
Finally, if the code reaches this point you can cast and compare the objects as you had done in your code:
A _obj = (A) obj;
return this.x == _obj.x;
Keep in mind that if the properties you are comparing are not primitives, you should use .equals on them
First of all, what do you mean by "making false true" exactly? I assume you want your code to run, but could you give us a bit more context of what you are trying to do?
The reason your code fails is that you are trying to cast your instance of an Object (a2) onto a reference of type A when you pass it into the equals method. But since a2 is actually a pure instance of Object and not of A, this cast fails. Even though Object is the baseclass for everything in Java, including your self defined A, you are casting in the wrong direction. An Object does not hold an attribute x so casting this way would be unsafe. Java's typechecking mechanism catches this and throws an error when you try to cast.
Have a look at a document explaining inheritance and casting to get the basics of this. E.g., this one.
According to many posts here, Assert.assertEquals should compare collections using deep insight, and two arrays of the same content should be equal.
I have JUnit 4.12 installed.
Calling
List<Integer[]> result, targetResult;
(both are created as ArrayList)
....
Assert.assertEquals("counted small array ", result, targetResult);
, where result and targetResult have the same content, the test fails though.
I have looked how the assertEquals do the job. For comparison of the Integer arrays it reached:
//----in AbstractList:
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator e2 = ((List) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
...
//and more deep, in Object:
public boolean equals(Object obj) {
return (this == obj);
}
And that means, that it compares simply references.
How can I make Assert.assertEquals() to work correctly?
The problem with assertEquals is the assumption that the equals(Object) is sane. Unfortunately, all arrays inherent from Object directly and have no specialised methods. This means that you have to call Arrays.equals(a, b) to compare two arrays, however if those arrays are inside a collection there is no way to do this conveniently.
Note: I don't know why printing [Ljava.lang.Integer#72173fed is a good toString for such an array either (it is something I have ranted against in my blog more than once)
And that means, that it compares simply hashcodes.
It doesn't compare hashCode()s, it compares references. hashCode()s are not memory addresses, nor can they be as they cannot change when the object is moved in memory.
If you want your data structures to be equal, use a collection which supports equals as you expect
List<List<Integer>> result
if you you want efficiency as int use 4 bytes and Integer can use 20 bytes including it's reference.
List<int[]> result
public static void assertEqualsArray(List<Int[]> a, List<int[]> b) {
// compare the list of arrays.
}
Consider:
Assert.assertArrayEquals(result.toArray(), targetResult.toArray());
I have serious problems when implementing a java library for use in Android.
I need global variables, I've solved this by applying Singleton.
But now I need to use variables without specifying the type.
As a solution I found using Object o.
Object o, how I check the type of o?
o.isArray () // Ok is type Array
But to know if it is int, double, ...?
Another solution to using Object or variable of any type?
For example:
public String arrayToString (Object o) {
if (o.getClass (). isArray ()) {
Arrays.toString return ((Object []) o);
Else {}
o.toString return ();
}
}
Object [] a = (Object []) LIB.getConf ("test");
a_edit [0] = "new value";
a_edit [1] = 2013;
x.arrayToString ("test") / / return test
x.arrayToString (1989) / / return 1989
x.arrayToString (a) / / return [new value, 2013]
thanks you,
Use the instanceof operator.
For example:
if (o instanceof Integer) {
//do something
} else if (o instanceof String) {
//do something else
} else if (o instanceof Object[]) {
//or do some other thing
} else if (o instanceof SomeCustomObject) {
//....
}
The Java language provides an operator "instanceof" to check the runtime type of an object. You could check if an object is of any type, simple doing the following:
if (o instanceof String) {
// The Object is an instance of a String
}
else if (o instanceof Double) {
// The Object is an instance of a Double
}
// And so on..
Another idea is to use the getClass, it works in a similar manner:
if (o1.getClass().equals(o2.getClass())) {
// The objects have the same class type
}
There is no type in Java that is a supertype of both reference types and primitive types. But there is an alternative. Each primitive type has a corresponding immutable wrapper type; e.g.
boolean -> Boolean
int -> Integer
char -> Character
So you can wrap an int as an Integer and then assign the resulting value to a variable of type Object. (And in fact, modern versions of Java provide syntactic sugar that does the "boxing" and "unboxing" automatically; see http://docs.oracle.com/javase/tutorial/java/data/autoboxing.html
Once you've assigned a value to a variable of type Object you can find out what its real type is using the instanceof operator ... or by using getClass().getName() to find out the type's name.
IN ADDITION JUST HAVE A LOOK AT
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#isPrimitive()
"There are nine predefined Class objects to represent the eight primitive types and void. These are created by the Java Virtual Machine, and have the same names as the primitive types that they represent, namely boolean, byte, char, short, int, long, float, and double."
I have a list of nodes. This nodes are a data class I defined by myself. Each node has a data field of the type Object. Now I want to find the node in a list of nodes that has the parameter object in the data field. I wrote this method, because I wanted to first compare if the two objects (the parameter and the object in the data field) are of the same type:
public Node getnNodeByData(Object obj) {
for (Node node : nodes) {
if (node.getData() instanceof obj.getClass()) {
}
}
}
Unfortunately this condition does not work:
Incompatible operand types boolean and Class<capture#1-of ? extends Graph>
I don't really know why this is a problem. How can I make this working?
No, you need to use Class.isInstance(Object). The instanceof keyword does not expect an object of type Class, but only the name of the class directly -- but Class.isInstance is basically analogous.
No, that is not possible like that. You should use isAssignableFrom() or isInstance(). The difference between the two methods is that isInstance(null) will return false and isAssignableFrom(null) will give true.
[object] instanceof [class]
should be translated to this:
[class].class.isAssignableFrom(object.getClass());
Example:
Integer i = 4;
boolean b = i instanceof Number;
boolean k = Number.class.isAssignableFrom(i.getClass());
b and k are equivalent.