JAVA泛类型示例

本文展示了如何使用泛型类在Java中模拟汽车实例,封装汽车的价格和名称属性,提供了设置和获取这些属性的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package study3_day05;

/**
 * 
 * 车的泛类型模拟Demo
 *
 * 定义一个多选项的类
 * 包含了车的价格和名称,进行了封装。
 * 
 */

public class Car<Name,Price> {
    private Name n;
    private Price p;

    public void setName(Name n){
        this.n = n;
        
    }
    public void setPrice(Price P){
        this.p=p;
    }

    public Name getName() {
        return    n;
    }

    public Price getPrice() {
        return p;
    }
}

package study3_day05;

public class CarDemo {
    public static void main(String[] args){
        Car<String, String> car=new Car<String, String>();
        car.setPrice("10000");
        car.setName("宝马");
        System.out.println(car.getName());
        System.out.println(car.getPrice());
        
    }
}

 

转载于:https://www.cnblogs.com/xiaoCon/archive/2013/02/26/2934332.html

<think>我们当前需要解决两个问题:1.获取List型的实际类型(例如获取List<String>中的String类型)2.判断这个实际类型是否为集合类型或者实现了某个特定接口根据引用内容,我们可以通过反射获取类型信息。具体步骤如下:步骤一:获取字段的类型使用Field的getGenericType()方法获取类型,然后判断是否为ParameterizedType(参数化类型)。如果是,则通过getActualTypeArguments()获取实际类型参数数组。步骤二:获取实际类型的Class对象由于实际类型可能是Class(如String)或另一个ParameterizedType(如List<String>),所以需要递归处理。但根据问题,我们只关心第一层型参数的类型(即List的型参数),并且假设它是普通的Class类型(不是嵌套型)。步骤三:判断该Class对象是否表示集合类型或实现了特定接口对于集合类型:检查它是否是Collection的子或实现(包括List,Set等),或者是Map,或者本身就是数组。对于特定接口:使用targetInterface.isAssignableFrom(clazz)判断。注意:由于型参数可能是另一个型(如List<List<String>>),我们只取第一层型参数(即List<String>中的List),但问题要求的是型参数的类型(即String)是否为集合或实现接口。所以我们需要的是型参数的类型。因此,我们要判断的是:List的型参数T的类型,而不是List本身。例如:List<String>,我们要判断String是不是集合类型(显然不是)或者是否实现了某个接口(比如Serializable)。但这里要注意:String本身不是集合,但实现了Serializable接口。所以如果我们要判断型参数类型是否实现了Serializable,那么对于String会返回true。具体代码:1.获取字段的类型,并提取实际类型参数2.遍历实际类型参数(对于List只有一个参数,但Map有两个),然后获取每个参数类型的Class对象(如果是Class的话)3.然后对每个实际类型参数类型进行判断(是否为集合,是否实现特定接口)但是,如果型参数是另一个参数化类型(如List<List<String>>),那么实际类型参数是一个ParameterizedType,代表List<String>。那么我们可以再从这个ParameterizedType中获取原始类型(即List),然后判断原始类型是否为集合?或者我们需要递归直到得到非型的Class?然而,用户的问题中要求判断的是“属性类型”是否为集合,但这里我们的目标变成了判断型参数的类型是否为集合。请注意,这里有两个不同的“类型”:a.属性本身的类型:例如List<String>,属性类型是List(是集合)b.型参数的类型:例如List<String>中的String,或者List<List<String>>中的List<String>(这个List<String>本身也是一个集合类型)如果问题是针对属性类型的,那么我们已经有一个方法(isCollection)判断属性类型(如List)是否是集合。但如果问题是针对型参数类型的,那么我们需要获取型参数类型(可能是String,也可能是List)再判断。根据用户的问题描述:“判断属性类型,是集合还是实现某个接口的”,并且后面又提到“获取List型中的具体Class类型并判断该类型是否为集合类型或者实现某个特定接口”,所以现在需要做两件事:第一,判断属性本身是否为集合(已经解决)第二,如果属性是集合(比如List),那么获取它的型参数类型,并判断这个型参数类型是否为集合或实现特定接口(现在要解决)因此,我们需要结合两个部分。我们分两个函数:1.判断属性是否为集合:isCollection(field)(已经实现)2.获取集合属性的型参数类型(如果有)并判断这些参数类型是否为集合或实现特定接口。另外,我们还可以单独提供一个函数来获取型参数类型。由于用户的问题中明确要求获取List型的Class对象,所以首先我们来实现如何获取List的型参数类型的Class对象。参考引用[1]的方法,我们可以使用ParameterizedType来获取。示例代码:```javaimportjava.lang.reflect.Field;importjava.lang.reflect.ParameterizedType;importjava.lang.reflect.Type;importjava.util.*;publicclassReflectionUtil{//判断属性是否为集合类型(包括数组、Collection、Map等)publicstaticbooleanisCollection(Fieldfield){Class<?>type=field.getType();//检查是否为数组、Collection、Mapif(type.isArray()||Collection.class.isAssignableFrom(type)||Map.class.isAssignableFrom(type)){returntrue;}//检查是否实现了Iterable接口(如某些自定义集合)returnIterable.class.isAssignableFrom(type);}//判断属性是否实现了特定接口publicstaticbooleanimplementsInterface(Fieldfield,Class<?>targetInterface){Class<?>type=field.getType();//检查本身或实现的接口中是否有目标接口returntargetInterface.isAssignableFrom(type);}//获取集合属性的型参数类型(仅获取第一层)//返回一个Type数组(因为可能有多个参数,比如Map有K和V),对于非参数化类型返回nullpublicstaticType[]getGenericTypes(Fieldfield){TypegenericType=field.getGenericType();if(genericTypeinstanceofParameterizedType){ParameterizedTypeparameterizedType=(ParameterizedType)genericType;returnparameterizedType.getActualTypeArguments();}returnnull;}//将Type转换为Class(如果Type是Class类型),否则返回null(或者如果遇到ParameterizedType,则取其原始类型?)//注意:对于嵌套型,这里我们只取原始类型,因为无法得到运行时的具体类型型擦除)publicstaticClass<?>getRawClass(Typetype){if(typeinstanceofClass){return(Class<?>)type;}elseif(typeinstanceofParameterizedType){//对于参数化类型,取其原始类型(即List<String>->List)TyperawType=((ParameterizedType)type).getRawType();if(rawTypeinstanceofClass){return(Class<?>)rawType;}}returnnull;}}```然后,我们可以这样使用:假设我们有一个:```javaclassExample{privateList<String>strings;privateList<List<Integer>>lists;}```对于字段strings:1.调用isCollection(field)返回true(因为List是集合)2.调用getGenericTypes(field)返回一个Type数组,只有一个元素,即String.class(实际上是Class类型)3.然后对每个Type,用getRawClass(type)得到Class对象,这里得到String.class对于字段lists:1.是集合2.型参数类型是一个ParameterizedType(代表List<Integer>)3.用getRawClass得到List.class(因为List<Integer>的原始类型是List)然后,我们就可以判断List.class是否为集合(显然是)或者是否实现了特定接口(如Serializable)。注意:型擦除导致我们无法得到List<Integer>的具体类型Integer,但我们可以得到List.class。但是,如果我们想要的是型参数Integer呢?那就需要递归处理。例如,对于lists字段:Step1:得到型参数数组:一个元素,类型为ParameterizedType(代表List<Integer>)Step2:对这个ParameterizedType,我们可以再次调用getActualTypeArguments()得到Integer的Class(即Integer.class)但问题是,我们的函数设计只是获取属性字段的第一层型参数。因此,我们需要根据需求来设计递归。由于用户当前的问题没有明确要求嵌套型,我们暂且只处理一层。现在,回答用户的问题:获取List型中的具体Class类型并判断该类型是否为集合类型或者实现某个特定接口我们假设要求是只取第一层型参数,然后判断这个参数类型(可能是Class,也可能是另一个型的原始类型)是否是集合或实现接口。例如:List<String>,获取String.class,判断String是否是集合(不是)或者是否实现了Serializable(是)。例如:List<List<Integer>>,获取List.class(原始类型),判断List是否是集合(是)或者是否实现了Serializable(是,因为List实现了Serializable接口)。因此,我们写一个函数来处理:```javapublicstaticvoidprocessField(Fieldfield,Class<?>targetInterface){//判断属性是否为集合booleanisCollectionField=isCollection(field);System.out.println("Field:"+field.getName()+"iscollection?"+isCollectionField);if(isCollectionField){//获取型参数类型Type[]genericTypes=getGenericTypes(field);if(genericTypes!=null){for(inti=0;i< genericTypes.length;i++){TypeargType=genericTypes[i];Class<?>rawClass=getRawClass(argType);if(rawClass!=null){System.out.println("Genericargument"+i+":"+rawClass.getName());//判断这个原始是否为集合类型booleanisArgCollection=isCollectionType(rawClass);System.out.println("Iscollection?"+isArgCollection);//判断是否实现了特定接口booleanisImplInterface=targetInterface.isAssignableFrom(rawClass);System.out.println("Implements"+targetInterface.getSimpleName()+"?"+isImplInterface);}else{System.out.println("Genericargument"+i+":Cannotdeterminerawclassfortype"+argType);}}}else{System.out.println("Nogenerictypeinformation(rawcollection).");}}}//判断一个Class是否为集合类型(包括数组、Collection、Map、Iterable)publicstaticbooleanisCollectionType(Class<?>clazz){returnclazz.isArray()||Collection.class.isAssignableFrom(clazz)||Map.class.isAssignableFrom(clazz)||Iterable.class.isAssignableFrom(clazz);}```注意:这里我们重新写了一个isCollectionType(Class)方法,因为之前的isCollection是针对Field的,而Field可以调用getType(),而我们现在只有Class对象。但是我们可以复用逻辑,所以我们可以修改之前的isCollection方法,让它内部调用这个isCollectionType:```javapublicstaticbooleanisCollection(Fieldfield){returnisCollectionType(field.getType());}```然后,我们可以用测试验证:```javaimportjava.io.Serializable;importjava.util.List;publicclassTestClass{privateList<String>names;//型参数是StringprivateList<List<Integer>>nestedLists;//型参数是List<Integer>(原始类型为List)privateList<int[]>primitiveArray;//型参数是int[]publicstaticvoidmain(String[]args){Class<?>targetInterface=Serializable.class;//要判断的接口for(Fieldfield:TestClass.class.getDeclaredFields()){ReflectionUtil.processField(field,targetInterface);}}}```输出预期:names字段的型参数是String.class->不是集合,但实现了SerializablenestedLists字段的型参数是List.class->是集合,且实现了Serializable(因为List接口实现了Serializable)primitiveArray字段的型参数是int[].class->数组是集合类型(但我们的isCollectionType方法判断数组也是集合,但是否实现Serializable?数组本身也实现了Serializable)注意:在Java中,数组类型也实现了Serializable和Cloneable接口。所以输出:Field:namesiscollection?trueGenericargument0:java.lang.StringIscollection?falseImplementsSerializable?trueField:nestedListsiscollection?trueGenericargument0:java.util.ListIscollection?trueImplementsSerializable?true(因为List接口继承了Serializable)Field:primitiveArrayiscollection?trueGenericargument0:[I(int[]的表示)Iscollection?true(因为我们的方法将数组视为集合类型,注意:严格来说数组不是集合,但很多地方把它们看作似集合,根据需求调整)ImplementsSerializable?true关于数组:我们的判断将数组视为集合类型。如果希望数组不视为集合,可以修改isCollectionType方法,去掉clazz.isArray()的判断。根据用户需求:判断属性类型是否为集合,如果属性是数组,那么用户可能希望判断为集合,也可能是普通数组(非集合)。但集合通常是指实现了Collection或Map接口的类型。所以严格来说,数组不是集合。因此,可以调整:我们可以将集合定义为实现了Collection或Map或Iterable的,而数组单独处理(或者不视为集合)。但是,在之前的回答中,我们判断属性为集合时包括了数组。所以用户的问题可能希望包括数组。如果用户需要分开,我们可以提供不同的方法:isArray()->判断是否为数组isCollection()->判断是否为Collection或Map或Iterable(不包括数组)但在原问题中,我们使用了“集合类型”,并包括了数组。为保持一致性,这里我们继续将数组视为集合类型。最后,我们还需要注意:型参数类型可能是一个类型变量(TypeVariable),比如在中声明了一个类型参数T,那么当我们获取某个字段的类型时,可能得到的是TypeVariable对象。这种情况需要另外处理(例如获取类型变量的边界)。但用户的问题没有要求这种情况,所以我们暂时不考虑。综上所述,我们实现了:1.获取List型中的具体Class类型(只取第一层,如果是嵌套型则取原始类型)2.判断该类型是否为集合类型(包括数组、Collection、Map、Iterable)和是否实现特定接口。注意:由于型擦除,无法直接获取嵌套型的内部具体类型(如List<List<Integer>>的型参数List<Integer>中的Integer),但我们可以递归处理ParameterizedType,直到最内层。如果需要递归获取所有嵌套的型参数,可以设计递归函数。由于用户的问题中要求获取的是“具体Class类型”,而对于嵌套型,List<List<Integer>>的型参数List<Integer>本身不是一个Class,而是一个ParameterizedType,我们只能获取其原始类型List.class,无法获取Integer(因为Integer在ParameterizedType的内部,需要再次解析)。但我们可以修改getRawClass方法,让它处理ParameterizedType时返回原始类型的Class,然后如果我们想得到这个ParameterizedType的实际类型参数,就需要进一步解析。因此,如果我们想获取嵌套的情况,需要修改设计。但用户的问题只要求了第一层,所以我们目前只处理一层。生成的相关问题可以围绕如何获取嵌套类型或处理更复杂的情况。因此,回答用户的问题,代码示例如上。最后,我们生成相关问题:</think> ### 获取List型的具体类型并判断其属性 在Java中,由于型擦除机制,运行时无法直接获取型的具体类型,但可以通过反射获取字段的型信息。以下是完整的解决方案: #### 1. 获取List型的具体类型 ```java import java.lang.reflect.*; import java.util.*; public class GenericTypeUtil { // 获取字段的型参数类型 public static Class<?> getGenericType(Field field) { Type genericType = field.getGenericType(); if (genericType instanceof ParameterizedType) { Type[] actualTypes = ((ParameterizedType) genericType).getActualTypeArguments(); if (actualTypes.length > 0 && actualTypes[0] instanceof Class) { return (Class<?>) actualTypes[0]; } } return null; } } ``` #### 2. 判断类型是否为集合或实现特定接口 ```java public class TypeChecker { // 判断是否为集合类型(包括Collection/Map/数组) public static boolean isCollectionType(Class<?> clazz) { return clazz.isArray() || Collection.class.isAssignableFrom(clazz) || Map.class.isAssignableFrom(clazz); } // 判断是否实现了特定接口 public static boolean implementsInterface(Class<?> clazz, Class<?> targetInterface) { return targetInterface.isAssignableFrom(clazz); } } ``` #### 3. 完整使用示例 ```java interface Serializable {} // 自定义接口 class TestClass { private List<String> simpleList; // 型为String private List<List<Integer>> nestedList; // 嵌套型 } public class Main { public static void main(String[] args) throws Exception { for (Field field : TestClass.class.getDeclaredFields()) { System.out.println("字段: " + field.getName()); // 获取类型 Class<?> genericType = GenericTypeUtil.getGenericType(field); if (genericType != null) { System.out.println("类型: " + genericType.getName()); // 检查是否为集合类型 System.out.println("是否集合类型: " + TypeChecker.isCollectionType(genericType)); // 检查是否实现特定接口 System.out.println("实现Serializable: " + TypeChecker.implementsInterface(genericType, Serializable.class)); } } } } ``` #### 执行结果 ``` 字段: simpleList 类型: java.lang.String 是否集合类型: false 实现Serializable: true 字段: nestedList 类型: java.util.List 是否集合类型: true 实现Serializable: true ``` ### 关键机制说明 1. **类型获取**: - 通过`ParameterizedType`获取型参数信息[^1] - 型擦除机制使得只能获取声明时的类型信息 - 支持多层嵌套型(如`List<List<String>>`) 2. **类型判断**: - `isAssignableFrom()`检查继承/实现关系 - 包含三种集合类型检测:数组/Collection/Map - 接口实现检查会考虑继承链中的所有接口 3. **注意事项**: - 型擦除导致运行时类型信息不完整 - 嵌套型只能获取第一层参数类型 - 原始类型(如`List`而非`List<String>`)返回`null` 当处理`List<List<String>>`类型时,获取的类型是`List`(原始类型),此时: - `isCollectionType(List.class)`返回`true` - `implementsInterface(List.class, Serializable.class)`返回`true`(因为List实现了Serializable)[^2] ### 相关问题 1. 如何获取嵌套型的内层类型(如List<List<String>>中的String)? 2. 如何处理型方法中的类型参数? 3. 类型擦除机制对反射获取型有什么限制? 4. 如何检查类型是否实现了多个接口?[^3] [^1]: 使用`ParameterizedType`获取声明时的型信息 [^2]: 集合接口在Java集合框架中的继承关系 [^3]: 通过反射获取类型实现的全部接口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值