反射与泛型

本文深入探讨Java反射机制的概念及应用,包括如何获取类信息、调用方法和访问属性等核心功能,并介绍泛型的基本原理及其优势。此外,还讨论了通配符的使用场景。
反射定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射并没有破坏程序的封装性,为了使代码拥有动态特性而生。
普通用法好比用遥控器操作电视机,而反射就是打开电视机用电路信号去操作电视机。


反射的常用方法:
1,获取类(返回的是Class的一个实例,也是一个对象):
Class.forName("packageName+className");
Object.getClass();
className.class;
2,调用某个对象具体的方法:
 Class cls = Class.forName("android.net.LinkProperties");
 Method meth = cls.getMethod("getRoutes");
 meth.setAccessible(true); //要记得设置权限
 routes = (Collection<RouteInfo>)meth.invoke(property);
3,获取某个对象的属性:
 Field fieldPassword = PrivateField.class.getDeclaredField("password");
        fieldPassword.setAccessible(true);
        PrivateField user = new PrivateField();
        Object password = fieldPassword.get(user);
        System.out.println(password.toString());


主要功能: 
在运行时判断任意一个对象所属的类;
在运行时构造任意一个类的对象;
在运行时判断任意一个类所具有的成员变量和方法;
在运行时调用任意一个对象的方法;
生成动态代理。


泛型定义:
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
使用泛型的地方基本都可以用Object实现,但是泛型不需要进行类型转换(输入类型参数时后面相关的都已转换),比Object更加方便。
现在List<Object>, List<String>是两种不同的类型(即便String继承了Object);
在List<String>中加入Object对象会出错,List<Object>可以添加String对象(这里很容易搞反)。

泛型使用实例:
class Gen<T> {
    private T ob; // 定义泛型成员变量
    public Gen(T ob) {
        this.ob = ob;
    }
    public T getOb() {  //调用这个方法时不需要转换类型
        return ob;
    }
    public void setOb(T ob) {
        this.ob = ob;
    }
    public void showType() {
        System.out.println("T的实际类型是: " + ob.getClass().getName());
    }
}


通配符:
◆ 如果你想从一个数据类型里获取数据,使用 ? extends 通配符,这又叫上限操作符。
使用<? extends O>时,说明这是O的一个子类,但不知道子类的具体类型,加入任何类型都可能导致类型不匹配,所以不能往里面加入除null以外的 任何对象;可以确定的是必然是O的子类,所以可以调用O的任意方法,也就是取。
◆ 如果你想把对象写入一个数据结构里,使用 ? super 通配符,又叫下限操作符。
使用<? super O>时,说明这是O的一个父类,所以可以往这个父类里面添加O或者O的子类对象;但是由于不知道父类的具体类型,所以不能取出任何非 Object类型的对象,这往往没什么意义。
◆ 如果你既想存,又想取,那就别用通配符,用普通的泛型就行。


T与?的区别:
T就是将类型固定,而?则不固定,比如下面这个例子:
public class CollectionGenFoo<T extends Collection> {
...
}
这么写就会报错
CollectionGenFoo<Collection> listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
需要改成:
CollectionGenFoo<ArrayList> listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
如果把 CollectionGenFoo<T extends Collection> 改成 CollectionGenFoo<? extends Collection>
可以这么写:
CollectionGenFoo<? extends Collection> listFoo = new CollectionGenFoo<ArrayList>(new ArrayList());
本质上两者没有区别,使用的时机不一样。当程序不依赖传入的泛型类型时应该使用?,其他时候使用T(例如返回值是T).







<think>我们正在讨论C#中反射的结合使用。用户要求提供示例用法和实现。根据引用[2]和[4],我们知道C#的在运行时是具体化的,即对于每个不同的类参数,都会生成一个特定的类。同时,反射允许我们在运行时检查类、创建对象、调用方法等。结合反射,我们可以动态地创建并调用其方法。步骤:1.获取的定义(例如:List<>)。2.使用MakeGenericType方法将定义转换为具体的(例如:List<int>)。3.然后,我们可以使用Activator.CreateInstance来创建该类的实例。4.对于方法,我们可以通过反射获取方法定义,然后使用MakeGenericMethod来指定类参数,再调用它。示例:假设我们有一个类:public classMyGenericClass<T>{publicvoid MyMethod(Tvalue){Console.WriteLine(value);}}我们想通过反射来创建MyGenericClass<string>的实例并调用其MyMethod方法。步骤详解:1.获取定义:Type genericTypeDef= typeof(MyGenericClass<>);2.创建具体的:Type constructedType =genericTypeDef.MakeGenericType(typeof(string));3.创建实例:objectinstance =Activator.CreateInstance(constructedType);4.获取MyMethod方法:MethodInfo method= constructedType.GetMethod("MyMethod");5.调用方法:method.Invoke(instance,new object[] {"HelloWorld"});另外,对于方法,例如:public classMyClass{public voidGenericMethod<T>(T value){Console.WriteLine(value);}}使用反射调用方法:1.获取类:Typetype =typeof(MyClass);2.创建实例:object instance= Activator.CreateInstance(type);3.获取方法定义:MethodInfomethodDef= type.GetMethod("GenericMethod");4.创建具体的方法:MethodInfogenericMethod= methodDef.MakeGenericMethod(typeof(string));5.调用:genericMethod.Invoke(instance, newobject[]{ "Hello"});注意:反射操作性能开销较大,应谨慎使用。根据用户要求,我们提供示例代码:```usingSystem;using System.Reflection; publicclass MyGenericClass<T>{public voidMyMethod(T value){Console.WriteLine($"MyMethod calledwith value: {value}");}} publicclass Program{publicstatic voidMain(){//示例1:反射创建类实例并调用方法//获取定义Type genericTypeDef= typeof(MyGenericClass<>);//创建具体类:MyGenericClass<string>Type constructedType =genericTypeDef.MakeGenericType(typeof(string));//创建实例objectinstance= Activator.CreateInstance(constructedType);//获取方法MethodInfo method= constructedType.GetMethod("MyMethod");//调用方法,传入字符串参数method.Invoke(instance,new object[] {"HelloReflection withGenerics!" });//示例2:反射调用方法//假设我们有一个包含方法的类Type myClassType= typeof(MyClass);objectmyClassInstance =Activator.CreateInstance(myClassType);MethodInfo genericMethodDef= myClassType.GetMethod("GenericMethod");//指定方法的类参数为intMethodInfogenericMethod= genericMethodDef.MakeGenericMethod(typeof(int));genericMethod.Invoke(myClassInstance,new object[] {123});} }public classMyClass{publicvoid GenericMethod<T>(Tvalue){Console.WriteLine($"GenericMethodcalled withvalue:{value}");} }```运行结果:MyMethodcalled withvalue:Hello Reflectionwith Generics!GenericMethod calledwith value:123注意:在实际应用中,反射可能会抛出异常(如方法不存在、参数不匹配等),应添加异常处理。相关问题: §§相关问题§§1.反射创建时,如何传递多个类参数?2.如何通过反射获取方法的类参数?3.反射结合使用时有哪些性能问题?如何优化?</think>### C# 反射结合使用示例 在 C# 中将反射结合使用时,核心是通过 `MakeGenericType` 和 `MakeGenericMethod` 实现动态类绑定。以下是具体示例: #### 1. 反射创建类实例 ```csharp // 定义类 public class Repository<T> { public void Add(T entity) => Console.WriteLine($"Added {typeof(T).Name}"); } // 反射创建实例 Type openType = typeof(Repository<>); Type closedType = openType.MakeGenericType(typeof(string)); object instance = Activator.CreateInstance(closedType); // 调用方法 MethodInfo addMethod = closedType.GetMethod("Add"); addMethod.Invoke(instance, new object[] { "Test" }); // 输出: Added String ``` #### 2. 反射调用方法 ```csharp public class DataProcessor { public T Process<T>(T input) => input; } // 动态调用方法 var processor = new DataProcessor(); MethodInfo method = typeof(DataProcessor).GetMethod("Process"); MethodInfo genericMethod = method.MakeGenericMethod(typeof(int)); int result = (int)genericMethod.Invoke(processor, new object[] { 42 }); Console.WriteLine(result); // 输出: 42 ``` #### 3. 检查定义 ```csharp Type listType = typeof(List<>); Console.WriteLine($"Is generic: {listType.IsGenericType}"); // True Console.WriteLine($"Type params: {string.Join(", ", listType.GetGenericArguments())}"); // T ``` #### 关键实现技术: 1. **`MakeGenericType(Type[])`** 将开放(如 `List<>`)转换为具体类(如 `List<string>`) 2. **`MakeGenericMethod(Type[])`** 为方法绑定具体类参数 3. **类判断方法** - `Type.IsGenericType`:检查是否为 - `Type.GetGenericTypeDefinition()`:获取原始定义 - `Type.ContainsGenericParameters`:检查是否存在未绑定的类参数 > **重要注意事项** > - 运行时类检查:当使用 `dynamic` 或反射时,编译器无法进行静态类检查[^4] > - 性能优化:反射操作开销较大,高频场景建议使用缓存或表达式树 > - 类安全:使用 `genericMethod.ReturnType` 和 `ParameterType` 验证类兼容性 --- ### 反射应用场景 1. **动态 ORM 实现** ```csharp Type repoType = typeof(Repository<>).MakeGenericType(entityType); object repository = serviceProvider.GetService(repoType); ``` 2. **插件系统** ```csharp Type pluginInterface = typeof(IPlugin<>).MakeGenericType(pluginType); var plugin = assembly.GetTypes().First(t => pluginInterface.IsAssignableFrom(t)); ``` 3. **序列化工具** ```csharp MethodInfo serializeMethod = typeof(Serializer) .GetMethod("Serialize") .MakeGenericModel(modelType); ``` [^1]: 声明语法参考 [^2]: .NET 运行时对的处理机制 [^4]: 动态类静态类安全权衡
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值