J'ai un tableau Object[]
Et j'essaie de trouver ceux qui sont des primitives. J'ai essayé d'utiliser Class.isPrimitive()
, mais il semble que je fasse quelque chose de mal:
int i = 3;
Object o = i;
System.out.println(o.getClass().getName() + ", " +
o.getClass().isPrimitive());
imprime Java.lang.Integer, false
.
Y a-t-il un bon moyen ou une alternative?
Les types dans un Object[]
_ ne sera jamais vraiment être primitif - car vous avez des références! Ici, le type de i
est int
alors que le type de l'objet référencé par o
est Integer
(en raison de la boxe automatique).
Il semble que vous ayez besoin de savoir si le type est un "wrapper for primitive". Je ne pense pas qu'il y ait quoi que ce soit construit dans les bibliothèques standard, mais c'est facile à coder:
import Java.util.*;
public class Test
{
public static void main(String[] args)
{
System.out.println(isWrapperType(String.class));
System.out.println(isWrapperType(Integer.class));
}
private static final Set<Class<?>> WRAPPER_TYPES = getWrapperTypes();
public static boolean isWrapperType(Class<?> clazz)
{
return WRAPPER_TYPES.contains(clazz);
}
private static Set<Class<?>> getWrapperTypes()
{
Set<Class<?>> ret = new HashSet<Class<?>>();
ret.add(Boolean.class);
ret.add(Character.class);
ret.add(Byte.class);
ret.add(Short.class);
ret.add(Integer.class);
ret.add(Long.class);
ret.add(Float.class);
ret.add(Double.class);
ret.add(Void.class);
return ret;
}
}
commons-langClassUtils
a des méthodes pertinentes .
La nouvelle version a:
boolean isPrimitiveOrWrapped =
ClassUtils.isPrimitiveOrWrapper(object.getClass());
Les anciennes versions ont la méthode wrapperToPrimitive(clazz)
, qui renverra la correspondance primitive .
boolean isPrimitiveOrWrapped =
clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
La bibliothèque Google de Google a un utilitaire Primitives qui vérifie si une classe est un type d’emballage pour une primitive: http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/primitives/ Primitives.html
Primitives.isWrapperType(class)
Class.isPrimitive () fonctionne pour les primitives
Pour ceux qui aiment le code laconique.
private static final Set<Class> WRAPPER_TYPES = new HashSet(Arrays.asList(
Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class));
public static boolean isWrapperType(Class clazz) {
return WRAPPER_TYPES.contains(clazz);
}
À partir de Java 1.5 et supérieur, il existe une nouvelle fonctionnalité appelée box automatique. Le compilateur le fait lui-même. Lorsqu'il voit une opportunité, il convertit un type primitif en classe de wrapper appropriée.
Ce qui se passe probablement ici est lorsque vous déclarez
Object o = i;
Le compilateur compilera cette déclaration en disant
Object o = Integer.valueOf(i);
Ceci est la boxe automatique. Cela expliquerait le résultat que vous recevez. Cette page de la Java 1.5 explique la boxe automatique plus en détail.
Integer
n'est pas une primitive, Class.isPrimitive()
ne ment pas.
public static boolean isValidType(Class<?> retType)
{
if (retType.isPrimitive() && retType != void.class) return true;
if (Number.class.isAssignableFrom(retType)) return true;
if (AbstractCode.class.isAssignableFrom(retType)) return true;
if (Boolean.class == retType) return true;
if (Character.class == retType) return true;
if (String.class == retType) return true;
if (Date.class.isAssignableFrom(retType)) return true;
if (byte[].class.isAssignableFrom(retType)) return true;
if (Enum.class.isAssignableFrom(retType)) return true;
return false;
}
Je pense que cela se produit en raison de boxe automatique.
int i = 3;
Object o = i;
o.getClass().getName(); // prints Integer
Vous pouvez implémenter une méthode utilitaire qui correspond à ces classes de boxe spécifiques et vous indique si une classe est primitive.
public static boolean isWrapperType(Class<?> clazz) {
return clazz.equals(Boolean.class) ||
clazz.equals(Integer.class) ||
clazz.equals(Character.class) ||
clazz.equals(Byte.class) ||
clazz.equals(Short.class) ||
clazz.equals(Double.class) ||
clazz.equals(Long.class) ||
clazz.equals(Float.class);
}
Vous devez faire face à la boxe automatique de Java.
Prenons le code
test de classe publique { public static void main (String [] args) { int i = 3; Objet o = i; revenir; } }javap -c test
Compilé à partir de "test.Java" Test de classe publique étend Java.lang.Object { Test public (); Code: 0: aload_0 1: invokespecial # 1; // Méthode Java/lang/Object. "" :() V 4: return
public static void main (Java.lang.String []); Code: 0: iconst_3 1: istore_1 2: iload_1 3: invokestatic # 2; // Méthode Java/lang/Integer.valueOf: (I) Ljava/lang/Integer; 6: astore_2 7: return
}
invokestatic # 2; // Méthode Java/lang/Integer.valueOf: (I) Ljava/lang/Integer;ce nouvel objet
Pour que vous puissiez voir qu'il est possible de renvoyer true avec isPrimitive (puisque vous avez suffisamment de réponses pour vous expliquer pourquoi il est faux):
public class Main
{
public static void main(final String[] argv)
{
final Class clazz;
clazz = int.class;
System.out.println(clazz.isPrimitive());
}
}
Ceci est important dans la réflexion lorsqu'une méthode utilise "int" plutôt qu'un "Integer".
Ce code fonctionne:
import Java.lang.reflect.Method;
public class Main
{
public static void main(final String[] argv)
throws Exception
{
final Method method;
method = Main.class.getDeclaredMethod("foo", int.class);
}
public static void foo(final int x)
{
}
}
Ce code échoue (impossible de trouver la méthode):
import Java.lang.reflect.Method;
public class Main
{
public static void main(final String[] argv)
throws Exception
{
final Method method;
method = Main.class.getDeclaredMethod("foo", Integer.class);
}
public static void foo(final int x)
{
}
}
Comme plusieurs personnes l'ont déjà dit, cela est dû à autoboxing .
Vous pouvez créer une méthode utilitaire pour vérifier si la classe de l'objet est Integer
, Double
, etc. Mais il y a aucun moyen de savoir si un objet a été créé en sélectionnant automatiquement une primitive ; une fois mis en boîte, il ressemble à un objet créé explicitement.
Donc, à moins que vous ne sachiez avec certitude que votre tableau ne contiendra jamais de classe wrapper sans auto-sélection, il n'y a pas de vraie solution.
Je suis en retard pour le spectacle, mais si vous testez un champ, vous pouvez utiliser getGenericType
:
import static org.junit.Assert.*;
import Java.lang.reflect.Field;
import Java.lang.reflect.Type;
import Java.util.Arrays;
import Java.util.Collection;
import Java.util.HashSet;
import org.junit.Test;
public class PrimitiveVsObjectTest {
private static final Collection<String> PRIMITIVE_TYPES =
new HashSet<>(Arrays.asList("byte", "short", "int", "long", "float", "double", "boolean", "char"));
private static boolean isPrimitive(Type type) {
return PRIMITIVE_TYPES.contains(type.getTypeName());
}
public int i1 = 34;
public Integer i2 = 34;
@Test
public void primitive_type() throws NoSuchFieldException, SecurityException {
Field i1Field = PrimitiveVsObjectTest.class.getField("i1");
Type genericType1 = i1Field.getGenericType();
assertEquals("int", genericType1.getTypeName());
assertNotEquals("Java.lang.Integer", genericType1.getTypeName());
assertTrue(isPrimitive(genericType1));
}
@Test
public void object_type() throws NoSuchFieldException, SecurityException {
Field i2Field = PrimitiveVsObjectTest.class.getField("i2");
Type genericType2 = i2Field.getGenericType();
assertEquals("Java.lang.Integer", genericType2.getTypeName());
assertNotEquals("int", genericType2.getTypeName());
assertFalse(isPrimitive(genericType2));
}
}
Les docs Oracle listent les 8 types primitifs.
Les types de wrapper primitve ne répondront pas à cette valeur. Ceci est destiné à la représentation en classe des primitifs, bien que, mis à part la réflexion, je ne puisse pas penser à de nombreuses utilisations. Donc, par exemple
System.out.println(Integer.class.isPrimitive());
affiche "faux", mais
public static void main (String args[]) throws Exception
{
Method m = Junk.class.getMethod( "a",null);
System.out.println( m.getReturnType().isPrimitive());
}
public static int a()
{
return 1;
}
imprime "vrai"
Découvrez BeanUtils à partir du printemps http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
La variante Apache (beans communs) a probablement des fonctionnalités similaires.
C'est le moyen le plus simple auquel je puisse penser. Les classes wrapper sont présentes uniquement dans Java.lang
paquet. Et en dehors des classes wrapper, aucune autre classe dans Java.lang
a un champ nommé TYPE
. Vous pouvez l'utiliser pour vérifier si une classe est une classe Wrapper ou non.
public static boolean isBoxingClass(Class<?> clazz)
{
String pack = clazz.getPackage().getName();
if(!"Java.lang".equals(pack))
return false;
try
{
clazz.getField("TYPE");
}
catch (NoSuchFieldException e)
{
return false;
}
return true;
}
vous pouvez déterminer si un objet est de type wrapper à l'aide des instructions suivantes:
***objClass.isAssignableFrom(Number.class);***
et vous pouvez également déterminer un objet primitif à l'aide de la méthode isPrimitive ()
Dix ans et cette question est toujours d'actualité, du moins pour moi ... Quel est le lien entre "isPrimitive" s'il ne fonctionne pas avec des instances de primitives? Je sais que la classe 'int.class' est primitive, je n'ai donc pas besoin de demander ceci ... Eh bien, j'ai écrit ceci:
import Java.lang.reflect.*;
class Test{
public static void main(String[] args) throws Exception{
char x=3; boolean b=true; int i=2;
Object o= i;
Object name =o.getClass().getField("TYPE").get(o);
System.out.println(""+name);
}
}
Cela retournera une chaîne comme "int", "char", "boolean", etc. Tous les huit primitifs ont une classe de wrapper qui a le champ "TYPE" qui contient ces valeurs. Le type vide le fait aussi.
Autre moyen, utilisation pratique:
import Java.util.*;
import Java.lang.reflect.*;
class Test{
static void print(Object O){System.out.println(O);}
public static void main(String[] args) throws Exception{
List list2 = new ArrayList<Object>(List.of("Word",2,3.0f,4.0,(char)65, a)); //where a= any user class instance.
//And see like this list simulates a Tuple like in Pyhton, another lack i see in Java.
//But indeed, this kind of List<Object> is still better then a immutable Tuple.
//And this was another of my doubts (tuples), and of other's people, as i've seen in my searchs at web.
ver(list2);
}
static void ver(List lis){
List prims = new ArrayList<String>(List.of("Boolean","Character","Byte","Double","Float","Integer","Long","Short"));
for(Object o: lis){
String s=o.getClass().getSimpleName();
print((prims.contains(s)?"Yes":"No"));
}
}
sortie: Non Oui Oui Oui Oui Non
public class CheckPrimitve {
public static void main(String[] args) {
int i = 3;
Object o = i;
System.out.println(o.getClass().getSimpleName().equals("Integer"));
Field[] fields = o.getClass().getFields();
for(Field field:fields) {
System.out.println(field.getType());
}
}
}
Output:
true
int
int
class Java.lang.Class
int