[英]Determining if an Object is of primitive type
我有一個Object[]
數組,我試圖找到那些是基元的。 我嘗試使用Class.isPrimitive()
,但似乎我做錯了什么:
int i = 3;
Object o = i;
System.out.println(o.getClass().getName() + ", " +
o.getClass().isPrimitive());
打印java.lang.Integer, false
。
有沒有正確的方法或其他選擇?
在該類型的Object[]
永遠不會真正原始的-因為你已經有了參考! 這里i
的類型是int
而o
引用的對象的類型是Integer
(由於自動裝箱)。
聽起來您需要確定該類型是否是“原始類型的包裝器”。 我認為標准庫中沒有為此內置任何內容,但是很容易編寫代碼:
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-lang ClassUtils
有相關的方法。
新版本有:
boolean isPrimitiveOrWrapped =
ClassUtils.isPrimitiveOrWrapper(object.getClass());
舊版本有wrapperToPrimitive(clazz)
方法,該方法將返回原始對應關系。
boolean isPrimitiveOrWrapped =
clazz.isPrimitive() || ClassUtils.wrapperToPrimitive(clazz) != null;
Google 的 Guava 庫有一個Primitives 實用程序,可以檢查類是否是原始類型的包裝器類型: Primitives.isWrapperType(class)
。
Class.isPrimitive() 適用於基元
對於那些喜歡簡潔代碼的人。
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);
}
從 Java 1.5 及更高版本開始,有一個稱為自動裝箱的新功能。 編譯器自己做這件事。 當它看到機會時,它會將原始類型轉換為其適當的包裝類。
這里可能發生的事情是當你聲明時
Object o = i;
編譯器會編譯這個語句說
Object o = Integer.valueOf(i);
這是自動裝箱。 這將解釋您收到的輸出。 Java 1.5 規范中的這個頁面更詳細地解釋了自動裝箱。
我認為這是由於自動裝箱。
int i = 3;
Object o = i;
o.getClass().getName(); // prints Integer
您可以實現一個與這些特定裝箱類匹配的實用方法,並在某個類是原始類時提供給您。
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);
}
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;
}
Integer
不是原始類型, Class.isPrimitive()
沒有說謊。
你必須處理java的自動裝箱。
讓我們拿代碼
public class test { public static void main(String [ ] args) { int i = 3; Object o = i; return; } }let's you inspect the generated bytecode. 你得到類 test.class 和讓你檢查生成的字節碼。
invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;如您所見,添加了 java 編譯器
調用靜態#2; //方法java/lang/Integer.valueOf:(I)Ljava/lang/Integer;in o via astore_2 從您的 int 創建一個新的整數,然后通過 astore_2存儲在 o 中
只是為了讓您看到 isPrimitive 有可能返回 true(因為您有足夠的答案告訴您為什么它是 false):
public class Main
{
public static void main(final String[] argv)
{
final Class clazz;
clazz = int.class;
System.out.println(clazz.isPrimitive());
}
}
當方法接受“int”而不是“Integer”時,這在反射中很重要。
此代碼有效:
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)
{
}
}
此代碼失敗(找不到方法):
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)
{
}
}
我遲到了,但如果你正在測試一個領域,你可以使用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));
}
}
Oracle 文檔列出了 8 種原始類型。
正如一些人已經說過的,這是由於自動裝箱。
您可以創建一個實用方法來檢查對象的類是否為Integer
、 Double
等。但是無法知道對象是否是通過自動裝箱原始對象創建的; 一旦被裝箱,它看起來就像一個明確創建的對象。
因此,除非您確定您的數組在沒有自動裝箱的情況下永遠不會包含包裝類,否則沒有真正的解決方案。
原始包裝器類型不會響應此值。 這是用於基元的類表示,盡管除了反射之外,我想不出太多的用途。 所以,例如
System.out.println(Integer.class.isPrimitive());
打印“假”,但
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;
}
打印“真”
這是我能想到的最簡單的方法。 包裝類只存在於java.lang
包中。 除了包裝類之外, java.lang
沒有其他類具有名為TYPE
字段。 您可以使用它來檢查類是否為 Wrapper 類。
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;
}
從 Spring 獲取 BeanUtils http://static.springsource.org/spring/docs/3.0.x/javadoc-api/
Apache 變體(commons beans)可能具有類似的功能。
您可以通過下面的語句確定對象是否為包裝類型:
***objClass.isAssignableFrom(Number.class);***
您還可以使用 isPrimitive() 方法確定原始對象
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
十年,這個問題仍然是最新的,至少對我來說......如果'isPrimitive'與原語實例不兼容,它的關系是什么? 我知道'int.class'是原始的,所以我不需要問這個......好吧,我做了這個:
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);
}
}
這將返回一個字符串,如“int”,“char”,“boolean”等。所有八個基元都有一個包裝類,它具有包含這些值的“TYPE”字段。 void類型也有。
另一種方式,實用:
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"));
}
}
輸出:否是是是是否
對於javapoet 的用戶,還有這種方式:
private boolean isBoxedPrimitive(Class<?> type) {
return TypeName.get(type).isBoxedPrimitive();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.