关于反射

在正常情况下,必须知道一个类的完整路径之后才可以实例对象,但是在java中也允许通过一个对象来找到其所在的类的信息,就是用到class类的功能。

 

Class类的功能

class X{

      

}

public class Test7 {

       public static void main(String[] args) {

              X x=new  X();

              //得到类所在的位置

              System.out.println(x.getClass().getName());

       }

}

 

在Object类中定义了以下的方法,此方法将被所有子类继承:

ü  Public final class getClass():此方法返回值类型是一个”class”类,实际上此类是java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象求出类的名称。

 

正常方式:引入需要的“包.类”名称-------------à同new实例化------------à取得实例化对象

反射机制:实例化对象--------------àgetClass()方法-------------à得到完整的“包.类”类名

 

 

Class类:

Class 本身表示了一个类的本身,通过class可以完整的得到一个类中的完整结构,包括此类的方法定义,属性定义等。

Class 没有构造方法,所以此类的构造方法都私有化了。

 

实例化class类对象有三种方法

       第一种:通过forName(完整包名+类名)方法

       第二种:类.class

       第三种:对象.getClass()

 

实例化class类对象的三种方式示例代码

class X{}

 

public class Test7 {

       public static void main(String[] args) throws ClassNotFoundException {

              //用自定义泛型

              Class<?> c1=null;

              Class<?> c2=null;

              Class<?> c3=null;

              //方式1:以下的操作形式是开发中最常用的一种反射机制形式Class.forName(String className);

              c1=Class.forName("X");

              //方式2:通过Object类中的方法实例化

              c2=new X().getClass();

              //方式3:通过类.class实例化

              c3=X.class;

              //得到类的名称

              System.out.println(c1.getName());

              System.out.println(c2.getName());

              System.out.println(c3.getName());

       }

}

 

一旦实例化class类之后,就可以进行反射的进一步操作。

Class主要是反射的源头,不光可以取得对象所在类的信息,也可以直接通过class类的方法进行对象的实例化操作,正常情况下,使用关键字new为对象实例化,如果现在已经实例化好了Class对象,则就可以通过class类中提供的newInstance()方法进行实例化。

 

 

使用newInstance()方法示例代码

class Person {

       private String name;

       private int age;

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

}

 

public class Demo1 {

       public static void main(String[] args) throws Exception {

                     Class<?> c1=null;

           //使用Class类中的forName(完整类名:包名.类名)方法,此方法返回一个Class对象

                     c1=c1.forName("com.jeremy.Test.Person");

                     Person p=null;

          //当对象已实例化好了,也可以通过对象.newInstance()方法来实例化对象

                     p=(Person)c1.newInstance();

                     p.setName("张三");

                     p.setAge(18);

                     System.out.println(p);

       }

}

通过以上的代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,反射的作用。

 

注意:A.在使用以上的操作的时候一定要记住一点,被实例化对象的类中必须存在无参构造方法,如果不存在的话,则肯定是无法实例化的。

B.对于以上的程序也并非没有解决办法,也是可以通过其他的方法进行实例化操作的,只是在操作的时候需要明确的调用类中构造方法,并将参数传递进去之后才可以之后才可以进行实例化操作。

       操作步骤:

1.     通过Class类中的getConstructors()取得本类的中全部构造方法。

2.     向构造方法中传递一个对象数组进去,里面包含了构造方法中所需的各个参数。

3.     之后通过Constructor实例化对象。

      

在constructor类中有一个newInstance(Object…initargs)传递初始化参数,进行对象的实例化操作。

 

Constructor类使用newInstance(Object…initargs)方法传递参数实例化对象的示例代码

class Person {

       private String name;

       private int age;

       public Person(String name,int age){

              this.name=name;

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

}

 

public class Demo1 {

       public static void main(String[] args) throws Exception {

                     Class<?> c1=null;

                     c1=c1.forName("com.jeremy.Test.Person");

          //通过Class类的getConstructors()方法得到类中的所有构造函数,得到一个构造函数类数组

                     Constructor<?>[] cons=c1.getConstructors();

                     Person p=null;

          //拿去某个构造函数类数组内某个构造函数类,用该Constructor类的newInstance()方法创建对象

                     p=(Person)cons[0].newInstance("张三",18);

                     System.out.println(p);

       }

}

 

但是,从实际角度看,如果要使用反射进行对象的实例化操作,最好在类中存在无参构造函数。

 

总结:

1.      本章的功能是class用的最多的功能,而且在开发中用户会经常使用到的开发模式。

2.      在使用Class实例化对象的时候,必须保证类中存在一个无参构造函数,否则无法使用。

3.      如果想要调用有参构造函数进行对象实例化操作,则必须使用Constructor类完成,此类表示构造函数方法,并通过可变变数传递要求的内容。

 

 

反射机制的深入--------取得类的结构

1.     可以使用反射取得实现的全部接口。

2.     可以使用反射取得一个类所继承的父类。

3.     可以使用反射取得一个类的全部构造方法。

4.     可以使用反射取得一个类中的全部方法。

5.     可以使用反射取得一个类中全部属性。

 

在实际开发中,以上的程序就是反射应用最多的地方,当然,反射机制所提供的功能远不止如此,还可以通过反射得到一个类的完整结构,那么这就要使用到java.lang.reflect包中的一下几个类:

       Constructor:表示类中的构造函数。

       Field:表示类中的属性。

       Method:表示类中的方法。

 

这三个类都是AccessibleObject类的子类。

-------------------|AccessibleObject类

-----------------------|Constructor表示类中的构造函数

-----------------------|Field表示类中的属性

-----------------------|Method表示类中的方法

 

如果想要取得一个类所实现的全部接口,则必须使用Class类中的getInterfaces()方法。

此方法定义如下:

       PublicClass[] getInterfaces()

此方法返回一个class类的对象数组,之后就可以直接利用class类中的getName()方法输出即可。

 

 

Class类中的getInterfaces()方法获得类实现的全部接口

interface Test1{}

interface Test2{}

interface Test3{}

interface china{

       public static final String NATIONAL="china";

       public static final String AUTHOR="张三";

       public void sayChina();

       public String sayHello(String name,String author);

}

class Person implements china,Test1,Test2,Test3{

       private String name;

       private int age;

       public Person(String name){

              this.name=name;

       }

       public Person(){}

       public Person(String name,int age){

              this(name);

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

       @Override

       public void sayChina() {

              System.out.println("作者:"+AUTHOR+",国籍:"+NATIONAL);

             

       }

       @Override

       public String sayHello(String name, String author) {

              return name+"你好!我今年"+age+"岁了";

       }

}

 

public class Demo1 {

       public static void main(String[] args) throws Exception {

                     Class<?> c1=null;

                     c1=Class.forName("com.jeremy.Test.Person");

           //Class.getInterfaces()方法:获得Class类中实现的全部接口,返回一个Class数组

                     Class[] interfaces=c1.getInterfaces();

                     for(int i=0;i<interfaces.length;i++){

                            System.out.println(interfaces[i].getName());

                     }

       }

}

 

 

取得父类

       一个类可以实现多个接口,但是只能继承一个父类,所以如果要想取得一个类的父类,可以直接使用Class类中的getSuperclass()方法。

此方法定义如下:

       PublicClass<? Super T> getSuperclass()

       此方法返回的是Class实例,和之前的得到接口一样,可以通过getName()方法取得名称。

 

示例代码

class Test4{}

interface china{

       public static final String NATIONAL="china";

       public static final String AUTHOR="张三";

       public void sayChina();

       public String sayHello(String name,String author);

}

//继承了Test4为父类

class Person extends Test4 implements china{

       private String name;

       private int age;

       public Person(String name){

              this.name=name;

       }

       public Person(){}

       public Person(String name,int age){

              this(name);

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

       @Override

       public void sayChina() {

              System.out.println("作者:"+AUTHOR+",国籍:"+NATIONAL);

             

       }

       @Override

       public String sayHello(String name, String author) {

              return name+"你好!我今年"+age+"岁了";

       }

}

 

public class Demo1 {

       public static void main(String[] args) throws Exception {

                     Class<?> c1=null;

                     c1=Class.forName("com.jeremy.Test.Person");

           //通过Class对象的方法:getSuperclass()获取对象的父类

                     Class<?> c2=c1.getSuperclass();

                     System.out.println(c2.getName());

       }

}

 

 

取得全部构造方法:

class Test4{}

interface china{

       public static final String NATIONAL="china";

       public static final String AUTHOR="张三";

       public void sayChina();

       public String sayHello(String name,String author);

}

class Person extends Test4 implements china{

       private String name;

       private int age;

       public Person(String name){

              this.name=name;

       }

       public Person(){}

       public Person(String name,int age){

              this(name);

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

       @Override

       public void sayChina() {

              System.out.println("作者:"+AUTHOR+",国籍:"+NATIONAL);

             

       }

       @Override

       public String sayHello(String name, String author) {

              return name+"你好!我今年"+age+"岁了";

       }

}

 

public class Demo1 {

       public static void main(String[] args) throws Exception {

                     Class<?> c1=null;

                     c1=Class.forName("com.jeremy.Test.Person");

                     Constructor<?>[] cons=c1.getConstructors();

                     for(int i=0;i<cons.length;i++){

                            System.out.println(cons[i]);

                     }

       }

}

 

以上的操作确实取得了类中的构造方法,但是此时通过对象直接打印取得的,肯定会调用Constructor类中toString()方法

       Constructor类中存在了以下的方法:

1.     获取修饰符:public int getModifiers()

2.     获取方法名称:public String getName()

3.     取得参数的类型:public Class<?>[] getParameterTypes()

 

 

获取构造函数各个部位的示例代码

class Test4{}

interface china{

       public static final String NATIONAL="china";

       public static final String AUTHOR="张三";

       public void sayChina();

       public String sayHello(String name,String author);

}

class Person extends Test4 implements china{

       private String name;

       private int age;

       public Person(String name){

              this.name=name;

       }

       public Person(){}

       public Person(String name,int age){

              this(name);

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

       @Override

       public void sayChina() {

              System.out.println("作者:"+AUTHOR+",国籍:"+NATIONAL);

             

       }

       @Override

       public String sayHello(String name, String author) {

              return name+"你好!我今年"+age+"岁了";

       }

}

 

public class Demo1 {

       public static void main(String[] args) throws Exception {

                     Class<?> c1=null;

                     c1=Class.forName("com.jeremy.Test.Person");

                     Constructor<?>[] cons=c1.getConstructors();

                     for(int i=0;i<cons.length;i++){

//得到构造方法中的全部参数

Class<?>[] p=cons[i].getParameterTypes();    

                            System.out.println("构造方法:");

              //得到构造函数的访问修饰符

                         System.out.print(cons[i].getModifiers()+" ");

              //获取构造函数的名字

                            System.out.print(cons[i].getName());

                            System.out.print("(");

                            for(int j=0;j<p.length;j++){

                                   System.out.print(p[j].getName()+"arg"+i);

                                   if(j<p.length-1){

                                          System.out.print(",");

                                   }

                            }

                            System.out.println("){}");

                     }

       }

}

 

执行以上代码,可以成功过取得构造方法的方法名及参数类型,但是在取得权限的时候发现返回的是一个数字而不是public,访问修饰符变为数字,这是因为在整个java中对于方法的修饰符是使用一定的数字表示出来的,而如果要想把这个数字还原成用户可以看懂的关键字,则必须依靠Modifier类完成,此类定义在java.lang.reflect包中。直接使用Modifier类的以下方法即可将修饰符:

Public staticString toString(ing mod);

Intmo=cons[i].getModifiers();

System.out.println(Modifier.toString());

 

 

还原访问修饰符

public class Demo1{

       public static void main(String[] args)throws Exception{

              Class<?> c1=null;

              c1=Class.forName("com.jeremy.Test.Person");

              Constructor<?>[] cons=c1.getConstructors();

              for(int i=0;i<cons.length;i++){

                     Class<?>[] p=cons[i].getParameterTypes();

                     System.out.print("构造方法:");

           //取得构造函数的访问修饰符,返回的是数字

                     int mo=cons[i].getModifiers();

           //通过Modifier类的toString()把数字转换成可以看得懂的访问修饰符

                     System.out.print(Modifier.toString(mo)+" ");

                     System.out.print(cons[i].getName());

                     System.out.print("(");

                     for(int j=0;j<p.length;j++){

                            System.out.print(p[j].getName()+"arg"+i);

                            if(j>p.length-1){

                                   System.out.print(",");

                            }

                     }

                     System.out.println("){}");

              }

       }

}

 

取得全部方法:

想要取得一个类中的全部方法,可以使用Class类中的getDeclaredMethods()方法,此方法返回一个 Method类的对象数组,而如果要想进一步取得方法的具体信息,例如:方法的参数,抛出的异常声明等等,则要必须依靠Method类

方法:

       PublicMethod[] getDeclaredMethods()thows SecuritvException------à输出本类中全部方法

       PublicMethod[] getMethods()thorws SecuritvException-----------à输出全部的方法

       PublicClass<?> getReturnType()----------à取得全部返回值

       PublicClass<?> getParameterTypes()---------à取得全部参数

       Public intgetModifiers()----------à取得修饰符

       PublicClass<?>[] getExceptionTypes()取得异常信息

 

Method类的使用

public class Demo1{

       public static void main(String[] args)throws Exception{

              Class<?> c1=null;

              c1=Class.forName("com.jeremy.Test.Person");

       //得到类中的所有方法

              Method[] m=c1.getMethods();

              for(int i=0;i<m.length;i++){

           //得到方法的返回值类型

                     Class<?> r=m[i].getReturnType();

           //得到方法的参数类型

                     Class<?>[] p=m[i].getParameterTypes();

           //得到方法的访问修饰符

                     int xx=m[i].getModifiers();

          //调用Modifier.toString(int mo):输出访问修饰符

                     System.out.print(Modifier.toString(xx)+" ");

                     System.out.print(r+" ");

           //得到方法的名字

                     System.out.print(m[i].getName());

                     System.out.print("(");

                     for(int j=0;j<p.length;j++){

              //输入参数的数据类型

                            System.out.print(p[j].getName()+""+"arg"+j);

                            if(j<p.length-1){

                                   System.out.println(",");

                            }

                     }

           //返回方法声明抛出的异常

                     Class<?>[] ex=m[i].getExceptionTypes();

                     if(ex.length>0){

                            System.out.print(")throws");

                     }else{

                            System.out.print(")");

                     }

                     for(int j=0;j<ex.length;j++){

              //输出异常的名字

                            System.out.print(ex[j].getName());

                            if(j<p.length-1){

                                   System.out.print(",");

                            }

                     }

                     System.out.println();

              }

       }

}

在一般的开发工具中经常看见随便提示功能,实际上次功能就是利用以上的程序完成的。

 

 

得到实现的接口或父类中的公共属性:public Field[] getFields()throws SecurityException

得到本类中的全部属性:public Field[] getDeclaredFields()throws SecurityException

 

以上方法返回的都是Field的数组,每个Field对象就表示类中一个属性

 

 

示例代码

public class Demo1{

       public static void main(String[] args)throws Exception{

              Class<?> c1=null;

       //通过反射机制,得到类对象

              c1=Class.forName("com.jeremy.Test.Person");

       //通过Class类对象的getFields()方法得到一个方法类数组

              Field[] f=c1.getFields();

              for(int i=0;i<f.length;i++){

                     //得到方法返回值属性类型

                     Class<?> r=f[i].getType();

           //得到访问修饰符

                     int mo=f[i].getModifiers();

          //调用Modifier.toString(mo):方法转换成我们看得懂的访问修饰符

                     String priv=Modifier.toString(mo);

                     System.out.print("公共属性:");

                     System.out.print(priv+" ");

           //输出方法返回值类型

                     System.out.print(r.getName());

          //输出方法名

                     System.out.print(f[i].getName());

                     System.out.println(",");

              }

       }

}

 

在正常情况下一个类的对象功能产生之后,就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚的知道要调用的方法名称,之后通过Class类中的:public MethodgetMethod(String name,Clsss<?>…parameterTypes)throwsNoSuchMethodException,SecurityException方法,得到一个方法的Method对象,之后通过此Method对象来执行方法,但是在方法调用的时候,因为会牵扯到方法中的参数的问题,所以通过getMethod()取得的时候,必须设置好需要的参数类型。

此方法返回一个Method类,通过此类的public Objectinvoke(Object obj,Object…args)throwsIllegalAccessException,IllegalArgumentException,InvocationTargetException方法执行调用方法。

 

示例代码

class Person extends Test4 implements china{

       private String name;

       private int age;

       public Person(String name){

              this.name=name;

       }

       public Person(){}

       public Person(String name,int age){

              this(name);

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

       @Override

       public void sayChina() {

              System.out.println("作者:"+AUTHOR+",国籍:"+NATIONAL);

             

       }

       public String sayHello(String name, int age) {

              return name+"你好!我今年"+age+"岁了";

       }

       @Override

       public String sayHello(String name, String author) {

              // TODO Auto-generated method stub

              return null;

       }

}

 

public class Demo1{

       public static void main(String[] args)throws Exception{

              Class<?> c1=null;

       //通过反射机制得到class对象

              c1=Class.forName("com.jeremy.Test.Person");

       //通过class对象的getMethod(String methodName,Class<?>…parameterTypes)注意:传递进去的参数类型一定要和方法一样,不然会报NoSuchMethodException异常

              Method m1=c1.getMethod("sayHello",String.class,int.class);

       //调用Method类的invoke(Object obj,Object…args)方法执行方法。

              System.out.println(m1.invoke(c1.newInstance(),"张三",18));

       }

}

 

 

通过反射调用属性

如果现在假设要操作一个类的属性,则可以通过Field完成,而不必麻烦通过setter和getter得到公共属性:

 

Public Field getField(String name)throws NoSuchFieldException,SecurityException

 

得到本类属性:

Public Field getDeclaredField(Stringname)throws NoSuchFieldException,SecurityxException

 

得到属性内容:

Public Object get(Object obj)throwsIllegalArgumentException,IllegalAccessException

 

示例代码

class Test4{}

interface china{

       public static final String NATIONAL="china";

       public static final String AUTHOR="张三";

       public void sayChina();

       public String sayHello(String name,String author);

}

class Person extends Test4 implements china{

       private String name;

       private int age;

       public Person(String name){

              this.name=name;

       }

       public Person(){}

       public Person(String name,int age){

              this(name);

              this.age=age;

       }

       public String getName() {

              return name;

       }

       public void setName(String name) {

              this.name = name;

       }

       public int getAge() {

              return age;

       }

       public void setAge(int age) {

              this.age = age;

       }

       @Override

       public String toString() {

              return "姓名:"+this.name+",年龄:"+this.age;

       }

       @Override

       public void sayChina() {

              System.out.println("作者:"+AUTHOR+",国籍:"+NATIONAL);

             

       }

       public String sayHello(String name, int age) {

              return name+"你好!我今年"+age+"岁了";

       }

       @Override

       public String sayHello(String name, String author) {

              // TODO Auto-generated method stub

              return null;

       }

}

 

public class Demo1{

       public static void main(String[] args)throws Exception{

              Class<?> c1=null;

              Object obj=null;

              c1=Class.forName("com.jeremy.Test.Person");

              obj=c1.newInstance();

              setter(obj,"name","张三",String.class);

              setter(obj,"age",30,int.class);

              System.out.print("姓名:");

              getter(obj,"name");

              System.out.print("年龄:");

              getter(obj,"age");

       }

       public static void setter(Object obj,String att,Object value,Class<?> type)throws Exception{

              Method m=obj.getClass().getMethod("set"+initStr(att),type);

              m.invoke(obj,value);

       }

       public static void getter(Object obj,String att)throws Exception{

              Method m=obj.getClass().getMethod("get"+initStr(att));

              System.out.println(m.invoke(obj));

       }

       public static String initStr(String old){

              String str=old.substring(0,1).toUpperCase()+old.toString();

              return str;

       }

}

 

 

暴力反射示例代码:

public static void main(String[] args)throws Exception{

              Class<?> c1=Class.forName("com.jeremy.Test.Person");

              //Field field=c1.getField("age");

              //因为age是私有属性,所以通过class.getField拿不到私有属性,此处出现NoSuchFieldException异常

              //System.out.println(field);

              Field field1=c1.getDeclaredField("age");

              //Class类中凡是getXXX的方法都是获得公共的成员,如果是Class类中getDeclaredXXX可以获得本类中全部的成员

              System.out.println(field1);

              Object obj=c1.newInstance();

              //通过ClassgetDeclaredField()方法得到的私有成员,不能对私有成员,进行操作。会出现IllegalArgumentException异常

              //可通过Field类父类AccessibleObjectsetAccessible(boolean flag)方法:值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查,

//简称暴力反射

              field1.setAccessible(true);

              field1.set(obj, 20);

              System.out.print(field1.get(obj));

       }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值