diff --git a/Java/10.注解.md b/Java/10.注解.md index b298697..8afe54e 100644 --- a/Java/10.注解.md +++ b/Java/10.注解.md @@ -1,43 +1,90 @@ +# 10. 注解 + +## 10.1 什么是注解 + +注解,一种元数据形式,提供有关程序的数据,该数据不属于程序本身。注释对其注释的代码的操作没有直接影响。 + +注解的语法: + +```java +@注解类型名 +``` -*注释*,一种元数据形式,提供有关程序的数据,该数据不属于程序本身。注释对其注释的代码的操作没有直接影响。 注释有多种用途,其中包括: -- **编译器信息**——**编译器**可以使用注释来检测错误或抑制警告。 -- **编译时和部署时处理**——软件工具可以处理注释信息以生成代码、XML 文件等。 -- **运行时处理**——一些注解可以在运行时检查。 - -### 内置的注解 - -Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。 - -**作用在代码的注解是** - -- @Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。 -- @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。 -- @SuppressWarnings - 指示编译器去忽略注解中声明的警告。 - -作用在其他注解的注解(或者说 元注解)是: - -- @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。 -- @Documented - 标记这些注解是否包含在用户文档中。 -- @Target - 标记这个注解应该是哪种 Java 成员。 -- @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类) - -从 Java 7 开始,额外添加了 3 个注解: - -- @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。 -- @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。 -- @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。 +* 编译前:为编译器提供编译检查的依据,辅助检查代码错误或抑制检查异常。 +* 编译中或发布时:给编译器提供信息生成代码或给其他工具提供信息生成文档等。 +* 运行时:在运行过程中提供信息给解释器,辅助程序执行。 + * 注解经常和反射结合起来用,多用于框架中。 -## 自定义注解 +## 10.2 内置的注解 -日常开发中我们使用class、interface比较多,而注解和它们一样,也是一种类的类型,他是用的修饰符为 @interface +### 10.2.1 Override -@元注解 +* 加在方法前 + +* 表示重写(覆盖)父类的方法; + +* 如果重写(覆盖)有错误,则报错。 + +* 因此重写父类方法,请加上@Override注解。 + + ```java + class Parent { + String name; + public Parent(){} + public Parent(String name) + { + this.name = name; + } + public void sayHello() + { + System.out.println("你好,我是" + name ); + } + } + + public class Child extends Parent + { + String name; + public Child{} + @Override + public void sayHello(String str) + { + //这里会报错 + super.sayHello(); + System.out.println("Hello,im Datawhale"); + } + } + + /** + 本段代码则不会提示错误 + + public class Child extends Parent + { + String name; + public Child{} + @Override + public void sayHello() + { + super.sayHello(); + System.out.println("Hello,im Datawhale"); + } + } + **/ + ``` + + + + +## 10.3 自定义注解 + +日常开发中我们使用class、interface比较多,而注解和它们一样,也是一种类的类型,他是用的修饰符为 @interface @元注解 + +使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,语法如下: ```java public @interface MyTestAnnotation { @@ -46,3 +93,33 @@ public @interface MyTestAnnotation { ``` +## 10.4 元注解 + +元注解负责注解其他注解。Java5.0定义了4个标准的meta-annotation类型,它们被用来提供对其它 annotation类型作说明。 +@Target, +@Retention, +@Documented, +@Inherited + +@Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。 + 取值(ElementType)有: +  1.CONSTRUCTOR:用于描述构造器 +  2.FIELD:用于描述域 +  3.LOCAL_VARIABLE:用于描述局部变量 +  4.METHOD:用于描述方法 +  5.PACKAGE:用于描述包 +  6.PARAMETER:用于描述参数 +  7.TYPE:用于描述类、接口(包括注解类型) 或enum声明 + +```java +@Target(ElementType.TYPE) +public @interface Table { + } + +@Target(ElementType.FIELD) +public @interface NoDBColumn { + +} +``` + +@Retention定义了该Annotation被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。 \ No newline at end of file diff --git a/Java/11.泛型.md b/Java/11.泛型.md index cd203f4..8e292a8 100644 --- a/Java/11.泛型.md +++ b/Java/11.泛型.md @@ -5,7 +5,6 @@ > 泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。 > > 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。 -> @@ -70,9 +69,44 @@ java: 对于add(int), 找不到合适的方法 泛型使得代码可以被不同类型的对象重用 -## 11.2 泛型方法 +## 11.2 泛型类 + +一个泛型类就是拥有一个或者多个类型变量的类。下面看一个简单例子: + +```java +public class test { + + public static class Point { + private T var; + + public void setVar(T x) { + this.var = x; + } + + public T getVar() { + return this.var; + } + + } + + public static void main(String[] args){ + Point p = new Point() ; + p.setVar(new Float(100.12f)) ; + System.out.println(p.getVar()); + } + +} +``` + +括号里面的T,是形式类型参数,可以随意指定,当类被使用的时候,就会使用具体的实际类型参数。 + +需要注意的是,泛型类只能用在成员变量上,并且只能使用引用类型。 + + + +## 11.3 泛型方法 下面是定义泛型方法的规则: @@ -81,43 +115,22 @@ java: 对于add(int), 找不到合适的方法 - 类型参数能被用来声明返回值类型,并且能作为泛型方法得到的实际参数类型的占位符。 - 泛型方法体的声明和其他方法一样。注意类型参数只能代表引用型类型,不能是原始类型(像int,double,char的等)。 -``` -/** - * 泛型方法的基本介绍 - * @param tClass 传入的泛型实参 - * @return T 返回值为T类型 - * 说明: - * 1)public 与 返回值中间非常重要,可以理解为声明此方法为泛型方法。 - * 2)只有声明了的方法才是泛型方法,泛型类中的使用了泛型的成员方法并不是泛型方法。 - * 3)表明该方法将使用泛型类型T,此时才可以在方法中使用泛型类型T。 - * 4)与泛型类的定义一样,此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型。 - */ -public T genericMethod(Class tClass)throws InstantiationException , - IllegalAccessException{ - T instance = tClass.newInstance(); - return instance; -} -``` - -## 11.3 泛型类 - -一个泛型类就是拥有一个或者多个类型变量的类。下面看一个简单例子: - ```java -ublic class Generic{ - //key这个成员变量的类型为T,T的类型由外部指定 - private T key; +public class MethodTest { + int var = 100; + String varStr = "Hello Datawhale"; + public T Method(T a) { + return a; + } + public static void main(String[] args) { + MethodTest t=new MethodTest(); + System.out.println(t.Method(t.var)); + System.out.println(t.Method(t.varStr)); + } + - public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定 - this.key = key; - } - - public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定 - return key; - } -} ``` @@ -126,44 +139,57 @@ ublic class Generic{ -``` -//定义一个泛型接口 -public interface Generator { - public T next(); -} +```java +class InfoImpl implements Info{ // 定义泛型接口的子类 + private String var ; // 定义属性 + public InfoImpl(String var){ // 通过构造方法设置属性内容 + this.setVar(var) ; + } + @Override + public void setVar(String var){ + this.var = var ; + } + @Override + public String getVar(){ + return this.var ; + } +} + +public class GenericsDemo24{ + public void main(String arsg[]){ + InfoImpl i = new InfoImpl("harvic"); + System.out.println(i.getVar()) ; + } +}; + ``` ## 11.5 类型通配符 -类型通配符一般是使用?代替具体的类型参数。例如 **List** 在逻辑上是**List,List** 等所有List<具体类型实参>的父类。 +类型通配符一般是在不确定具体参数时候,使用?代替。?表示未知类型,类型参数赋予不确定值,只能用在声明类型、方法参数上,不能用在定义泛型类上 - - -``` -import java.util.*; +```java +public class match { -public class GenericTest { - - public static void main(String[] args) { - List name = new ArrayList(); - List age = new ArrayList(); - List number = new ArrayList(); - - name.add("icon"); - age.add(18); - number.add(314); + public static void test(List list) { - getData(name); - getData(age); - getData(number); - - } + List list2; + list2 = new ArrayList(); + list2 = new ArrayList(); + list2 = new ArrayList(); + + } + + public static void main(String[] args) { + test(new ArrayList()); + test(new ArrayList()); + } - public static void getData(List data) { - System.out.println("data :" + data.get(0)); - } } + ``` + + diff --git a/Java/9.反射.md b/Java/9.反射.md index b650f85..49c18f8 100644 --- a/Java/9.反射.md +++ b/Java/9.反射.md @@ -1,11 +1,9 @@ -# 反射 +# 9. 反射 -## 反射概述 +## 9.1 反射概述 JAVA反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。 - - **反射的功能**: 1. 在运行时获取任意一个对象所属的类型信息,包括修饰符、泛型、父类、实现的接口、注解等; @@ -13,8 +11,6 @@ JAVA反射是在运行状态中,对于任意一个类,都能够知道这个 3. 在运行时获取任意一个类所具有的构造方法、成员变量和方法; 4. 在运行时访问任意一个对象的成员变量和方法; - - **反射的应用**: 1. 通过使用类全名创建类实例来使用外部用户定义的类。 @@ -38,20 +34,26 @@ JAVA反射是在运行状态中,对于任意一个类,都能够知道这个 -**使用反射的注意事项**: -反射是强大的,但不应滥用。如果可以在不使用反射的情况下进行操作,则优选避免使用反射。 -反射增加了JVM的系统开销,性能上比不使用反射慢。 -反射可能违反某些安全策略。 -反射允许访问私有成员,打破了封装,可能破坏可移植性。 +## 9.2 使用反射 -## Class类 +### 9.2.1 Class类 java.lang.Class类是所有Reflection API的切入点,是所有反射操作的入口。 在Java程序运行过程中,对程序中每种类型的对象,Java虚拟机都会实例化一个不可变的java.lang.Class实例,每个对象都是引用或者原始类型。 -引用类型都继承自java.lang.Object。 类,枚举,数组和接口都是引用类型。 -原始类型包括:boolean,byte,short,int,long,char,float和double + + + +反射机制里主要会用到以下四种类 + +1.java.lang.Class.java:类对象; + +2.java.lang.reflect.Constructor.java:类的构造器对象; + +3.java.lang.reflect.Method.java:类的方法对象; + +4.java.lang.reflect.Field.java:类的属性对象; @@ -59,70 +61,135 @@ java.lang.Class类是所有Reflection API的切入点,是所有反射操作的 **1.获取Class实例的三种方法,最常用的是第3种;** - 对象.getClass() - 类型名.class - Class.forName() +1. 对象.getClass() +2. 类型名.class +3. Class.forName() +​ (示例代码于code/ClassEx.java) +**2.获取类的成员** -**2.用Class实例创建对象** +这时候就用到了java.lang.reflect.Field.java类。一个Field提供类或接口中一个成员变量(属性)的信息,也可以动态访问。 + +Class中提供了两类用于访问成员变量,成员方法和构造方法的方法: + +1. 列出所有成员的方法 +2. 根据名字搜索特定成员的方法 ```java -//2.1通过newInstence(),此方式只适用于无参构造 -Phone instance1 = (Phone) clazz1.newInstance(); -//2.2先调用构造器,再通过newInstence()创建 -Constructor[] cons = clazz1.getConstructor(); -//假设第一个为无参构造 -Phone instance2 = cons[0].newInstance(); -//假设第二个构造方法为两个String类型参数 -Phone instance3= cons[1].newInstance("s1","s2"); +public Field getDeclaredField(String name) +//根据名字获取类中定义的成员变量,不包括继承父类的成员 + +public Field getField(String name) +//根据名字获取类中定义的公有成员变量,包括继承父类的成员 + +public Field[] getDeclaredFields() +//获取类中声明的所有成员变量,返回Field[]类型,不含继承父类的成员 + +public Field[] getFields() +//获取类中声明的所有公有成员变量,返回Field[]类型 +``` + +​ (示例代码于 code/RefEx) + +**3.获取类的成员方法** + + + +```java +public Method getDeclaredMethod(String name, + Class... parameterTypes) +//根据名字获取类中定义的成员方法,不包括继承父类的成员方法 + +public Method getMethod(String name, + Class... parameterTypes) +//根据名字获取类中定义的公有成员方法,包括继承父类的成员方法 + +public Method[] getDeclaredMethods() +//获取类中声明的所有成员方法,返回Method[]类型,不含继承父类的成员 + +public Method[] getMethods() +//获取类中声明的所有公有成员方法,返回Method[]类型 +``` + +​ (示例代码于 code/RefEx) + + + +**4.获取类的构造方法** + + + +```java +public Constructor getDeclaredConstructor(Class… parameterTypes) +//根据参数类型列表获取类中定义的构造方法 + +public Constructor getConstructor(Class… parameterTypes) +//根据参数类型列表获取类中定义的公有构造方法 + +public Constructor[] getDeclaredConstructors() +//获取类中声明的所有构造方法,返回Constructor[]类型 + +public Constructor[] getConstructors() +//获取类中声明的所有公有构造方法,返回Constructor[]类型 + ``` -**3.获取指定属性Field和所有的属性Field** -获取成员变量的类型信息(了解)。 -``` -Class c = Class.forName(className); -Field field = c.getField(fieldName); -Class typeClass = field.getType(); -Type type = field.getGenericType(); -``` +**5.调用成员方法** -**4.用反射的方式给对象的属性设置值,获取对象的属性值** - -获取指定的方法Method和所有的方法Method - -用反射的方式调用方法,获取调用的方法的返回值 - -获取指定的构造方法Constructor和所有构造方法Constructor +**Method.invoke(Object obj, Object... args)**实现方法调用,多用于不得不用反射的的情况下。 +第一个参数是调用这个方法的类实例,如果该方法是静态的,第一个参数为null +后面几个参数是该方法的参数,如果方法没有参数,可以省略 -**通过Constructor实例创建对象。** +调用成员方法的案例:示例代码见 code/Deet.java + + + +**6.用反射的方式给对象的属性设置值,获取对象的属性值** + +* 给定类的实例,可以使用反射来设置该类实例中成员变量的值。 +* 通常是以常规方式无法设置的情况下才这样操作。 +* 因为这种访问违反了类的封装性的设计意图,耗费额外的系统开销,所以应该尽可能的酌情使用。 + +​ (示例代码见 code/Test.java) + + + +7**.通过Constructor实例创建对象。** 创建类实例(类对象)(重点掌握): 常规情况下是使用new操作符调用类的构造方法来创建类实例: -``` +```java Date date = new Date(); ``` 使用反射创建类实例有两种方法: -``` +```java Class.newInstance() +//只能调用类的无参数的非私有构造方法 +//抛出构造方法的异常 Constructor.newInstance(Object... initargs) +//可以调用类的任何构造方法 +//用InvocationTargetException封装异常来抛出 ``` -Class.newInstance() - 只能调用类的无参数的非私有构造方法 - 抛出构造方法的异常 -Constructor.newInstance(Object... initargs) - 可以调用类的任何构造方法 - 用InvocationTargetException封装异常来抛出 \ No newline at end of file + + + + +**使用反射的注意事项**: +反射是强大的,但不应滥用。如果可以在不使用反射的情况下进行操作,则优选避免使用反射。 +反射增加了JVM的系统开销,性能上比不使用反射慢。 +反射可能违反某些安全策略。 +反射允许访问私有成员,打破了封装,可能破坏可移植性。 \ No newline at end of file diff --git a/Java/README.md b/Java/README.md index 2066072..3cedad5 100644 --- a/Java/README.md +++ b/Java/README.md @@ -7,7 +7,7 @@ | 赖桂彬 | 广州城市理工学院 | | | 梁家晖 | 广州城市理工学院,Datawhale成员 | https://github.com/leungkafai | | 陈玉林 | 广州城市理工学院 | | -| 潘梓琪 | | | +| 潘梓琪 | 广州城市理工学院 | | | 周思阳 | 武汉理工大学,物流管理硕士 | https://github.com/suifengyougu | @@ -31,41 +31,41 @@ - 组队、修改群昵称 - 熟悉打卡规则。 -### Task01:(2天) +### Task01:Java简介与环境配置(2天) 0.java简介与安装配置 1.基本数据类型与变量 -### Task02:(2天) +### Task02:初始Java语言基础(2天) 2.运算符和表达式 3.控制流程 -### Task03:(1天) +### Task03:Java数组(1天) 4.数组 -### Task04:(3天) +### Task04:面向对象编程基础(3天) 5.类与方法 6.继承与多态 -### Task05:(3天) +### Task05:面向对象核心技术(3天) 7.抽象类与接口 8.异常处理 -### Task06:(3天) +### Task06:反射与注释(3天) 9.反射 10.注解 -### Task07: (2天) +### Task07: 泛型(2天) 11.泛型 @@ -77,4 +77,4 @@ >Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。Datawhale以“for the learner,和学习者一起成长”为愿景,鼓励真实地展现自我、开放包容、互信互助、敢于试错和勇于担当。同时Datawhale 用开源的理念去探索开源内容、开源学习和开源方案,赋能人才培养,助力人才成长,建立起人与人,人与知识,人与企业和人与未来的联结。 -​ \ No newline at end of file +​ diff --git a/Java/code/ClassEx.java b/Java/code/ClassEx.java new file mode 100644 index 0000000..2175e7d --- /dev/null +++ b/Java/code/ClassEx.java @@ -0,0 +1,113 @@ +package 类; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +enum E { A, B };//枚举类型E + +public class ClassEx { + + public static void main(String[] args) throws Exception { + + //第1种获取Class实例的方法 :对象名.getClass(),原始类型、接口类型对应的Class实例不能用这种方法获取 + //类类型 + Class c = "foo".getClass(); + System.out.println(c); + + + + c = System.out.getClass(); + System.out.println(c); + + Date date=new Date(); + c=date.getClass(); + System.out.println(c); + + //接口类型 + List array=new ArrayList(); + c=array.getClass(); + System.out.println(c); + + //数组类型 + int[] a=new int[10]; + c=a.getClass(); + System.out.println(c+" "+c.getCanonicalName()); + + char[] b=new char[10]; + c=b.getClass(); + System.out.println(c+" "+c.getName()); + + double[] d=new double[10]; + c=d.getClass(); + System.out.println(c); + + long[] l=new long[10]; + c=l.getClass(); + System.out.println(c); + + Date[] f=new Date[10]; + c=f.getClass(); + System.out.println(c+" "+c.getCanonicalName()); + + //枚举类型 + E e=E.A; + c=e.getClass(); + System.out.println(c); + + System.out.println("*****************************"); + + //基本类型,编译错误 + //int a=10; + //c=a.getClass(); + + //第2种获取Class实例的方法 :类型名.class,所有类型对应的Class实例都可以用这种方法获取 + c=String.class; + System.out.println(c); + + c=Date.class; + System.out.println(c); + + c=List.class; + System.out.println(c); + + c=int.class; + System.out.println(c); + + c=int[][].class; + System.out.println(c); + + c=Date[][].class; + System.out.println(c); + + c=E.class; + System.out.println(c); + + System.out.println("*****************************"); + + //第3种获取Class实例的方法 :Class.forName(类全名字符串),原始类型对应的Class实例不可以用这种方法获取 + c=Class.forName("java.lang.String"); + System.out.println(c); + + c=Class.forName("java.util.List"); + System.out.println(c); + + c=Class.forName("[I");//int数组类型int[] + System.out.println(c); + + c = Class.forName("[D");//double型数组double[] + System.out.println(c); + + c = Class.forName("[[Ljava.lang.String;");//String二维数组String[][] + System.out.println(c); + + c=Class.forName("类.E"); + System.out.println(c); + + System.out.println("*****************************"); + + //基本类型包装类中的TYPE成员的值是基本类型对应的Class类实例 + c=Double.TYPE; + System.out.println(c); + c=Void.TYPE; + System.out.println(c); + } +} diff --git a/Java/code/Deet.java b/Java/code/Deet.java new file mode 100644 index 0000000..fadf682 --- /dev/null +++ b/Java/code/Deet.java @@ -0,0 +1,54 @@ +package 方法; +import static java.lang.System.out; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.Locale; +public class Deet { + private boolean testDeet(Locale l) { + out.format("Locale = %s, Language Code = %s%n", l.getDisplayName(), l.getLanguage()); + return true; + } + private boolean testFoo(Locale l) { + return false; + } + private boolean testBar() { + return true; + } + public static void main(String... args) { + try { + //获取Deet类的Class实例 + Class c = Deet.class; + //有Class实例创建一个类对象 + Object t = c.newInstance(); + + //获取Class实例对应的类型声明的所有的方法 + Method[] allMethods = c.getDeclaredMethods(); + for (Method m : allMethods) { + String mname = m.getName();//获取方法的名字 + //如果方法的名字不以test开头,或者返回类型不是boolean型 + if (!mname.startsWith("test") || (m.getReturnType() != boolean.class)) { + continue; + } + //获取方法的所有参数类型 + Type[] pType = m.getGenericParameterTypes(); + //如果有参数,并且第一个参数是Locale类型 + if ((pType.length != 1) || Locale.class.isAssignableFrom(pType[0].getClass())) { + continue; + } + out.format("调用 %s()%n", mname); + try { + //调用方法,o是方法返回值 + Object o = m.invoke(t, Locale.CHINA); + out.format("%s() 返回 %b%n%n", mname, (Boolean) o); + } catch (InvocationTargetException x) { + x.printStackTrace(); + } } + } catch (InstantiationException x) { + x.printStackTrace(); + } catch (IllegalAccessException x) { + x.printStackTrace(); + } + } + +} diff --git a/Java/code/RefEx.java b/Java/code/RefEx.java new file mode 100644 index 0000000..bc1c9e2 --- /dev/null +++ b/Java/code/RefEx.java @@ -0,0 +1,78 @@ +package test; + +import static java.lang.System.out; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.util.ArrayList; + +public class RefEx { + + public static void main(String[] args) { + // TODO Auto-generated method stub + String s="hello"; + Class c=s.getClass();//获取类型 + System.out.println(c); + String modifiers=Modifier.toString(c.getModifiers());//获取修饰符 + System.out.println(modifiers); + + TypeVariable[] tv = c.getTypeParameters();//获取泛型类型参数 + if (tv.length != 0) { + out.format(" "); + for (TypeVariable t : tv) + out.format("%s ", t.getName()); + out.format("%n%n"); + } else { + out.format(" -- No Type Parameters --%n%n"); + } + + Class superclass=c.getSuperclass();//获取类型的父类 + System.out.println(superclass); + + Type[] intfs = c.getGenericInterfaces();//获取类实现的接口 + if (intfs.length != 0) { + for (Type intf : intfs) + out.format(" %s%n", intf.toString()); + out.format("%n"); + } else { + out.format(" -- No Implemented Interfaces --%n%n"); + } + + Annotation[] ann = c.getAnnotations();//获取类的注解 + if (ann.length != 0) { + for (Annotation a : ann) + out.format(" %s%n", a.toString()); + out.format("%n"); + } else { + out.format(" -- No Annotations --%n%n"); + } + + Constructor[] cons=c.getDeclaredConstructors();//获取类的构造方法 + for(Constructor con:cons){ + System.out.println(con.toGenericString()); + + } + out.format("%n%n"); + + Field[] fs=c.getDeclaredFields();//获取类的数据成员(成员变量) + for(Field f:fs){ + System.out.println(f.toGenericString()); + + } + out.format("%n%n"); + + Method[] ms=c.getMethods();//获取类的公有成员方法(包含从父类继承的) + for(Method m:ms){ + System.out.println(m.toGenericString()); + + } + out.format("%n%n"); + + } + +} diff --git a/Java/code/Test.java b/Java/code/Test.java new file mode 100644 index 0000000..bee1bd0 --- /dev/null +++ b/Java/code/Test.java @@ -0,0 +1,87 @@ +package test; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class Test { + public static String classname="类.Student"; + public static String fieldname="name"; + public static String methodname="setName"; + public static String[] mptypes= {"java.lang.String"}; + public static Object fvalue=new String("xiaolin"); + public static Object mp1=new String("xiaohong"); + + + public static void main(String[] args) { + // TODO Auto-generated method stub + try { + Class c=Class.forName(classname);//根据类名字符串获得类对应的Class实例 + //第一种用反射创建类对象的方法,相当于调用类的无参数构造方法 + Object o=c.newInstance();//Student o=new Student(); + + //使用反射访问类对象的属性(给属性设置值,获取属性的值) + Field f=c.getDeclaredField(fieldname);//根据Field名,获得Field对象 + f.setAccessible(true); + f.set(o,fvalue);//o.name="xiaolin";使用反射给o对象的f代表的属性设置值为发value的值 + System.out.println(f.get(o));//获取o对象的f属性对应的值,并输出 + + + + @SuppressWarnings("unchecked") + //使用反射调用对象的方法 + //使用反射根据方法名,和参数类型、参数数量来获取具体某个方法 + Method m=c.getDeclaredMethod(methodname, Class.forName(mptypes[0]));//String.class + //方法的调用,调用o对象的m方法,方法的实际参数是mp1,mo是方法调用的返回值 + Object mo=m.invoke(o,mp1);//o.setName("xiaohong"); + System.out.println(mo); + //调用了o对象名为setAge,参数有1个,类型是int型的方法,实际参数是21 + m=c.getDeclaredMethod("setAge", int.class); + m.invoke(o, 21); + System.out.println(o); + + /*Method m=c.getDeclaredMethod(methodname); + Object mo=m.invoke(o); + System.out.println(mo); + System.out.println(f.get(o));*/ + + @SuppressWarnings({ "unchecked", "rawtypes" }) + //第二种用反射创建类对象的方法,先获取具体的Constructor,再用Constructor去创建对象 + Constructor con=c.getDeclaredConstructor(String.class,int.class);//根据构造方法参数类型来获取某个构造方法 + Object o1=con.newInstance("Mary",20); + //用Constructor创建类对象,相当于Student o1=new Student("Mary",20); + System.out.println(o1); + + + + } catch (ClassNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchFieldException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (SecurityException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InstantiationException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalAccessException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IllegalArgumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + + } + +}