Java基础-注解 & 反射(十一)
文章目录
- 一、注解入门
-
- 1.注解概述
- 2.注解分类
-
- 2.1 内置注解
- 2.2 自定义注解
- 2.3 元注解
- 二、反射
-
- 2.1 Java反射机制概述
-
- 2.1.1 反射机制与应用
- 2.1.2 反射的优点和缺点
- 2.1.3 反射相关的主要API
- 2.2 理解Class类并获取Class实例
-
- 2.2.1 Class类的常用方法
- 2.2.2 获取Class类的实例
- 2.2.3 哪些类型可以有Class对象
- 2.2.4 Java内存分析
- 2.3 创建运行时类的对象
-
- 2.3.1 了解类的加载过程
- 2.3.2 类的加载与ClassLoader的理解
- 2.3.3 什么时候会出现类初始化?
- 2.4 类的加载与ClassLoader
-
- 2.4.1 类加载器的作用
- 2.5 获取运行时类的完成结构
- 2.6有了Class对象能做什么呢?
- 2.7 调用运行时类的指定结构
-
- 2.7.1 调用指定的方法
- 2.8 反射操作泛型(了解)
- 2.9 反射操作注解
一、注解入门
1.注解概述
/ * @author Daniel * 注解概述 */public class ZhuJieDaniel extends Object{ //Override 重写的注解 @Override public String toString() { return super.toString (); }}
2.注解分类
2.1 内置注解
/ * @author Daniel * 注解概述 */@SuppressWarnings ( "all" )//镇压警告注解 有此注解public不会出现底纹颜色public class ZhuJieDaniel extends Object{ //Override 重写的注解 @Override public String toString() { return super.toString (); } @Deprecated //不鼓励程序员使用,但是可以使用,或者有更好的方式 public static void test1(){ System.out.println ("Deprecated"); } public static void test2(){ System.out.println ("SuppressWarnings"); } public static void main(String[] args) { test1 ();// test2 (); }}
运行结果为:
2.2 自定义注解
/ * @author Daniel * 自定义注解 */public class ZiDingYiAnnonotion { //注解可以显示赋值,如果没有默认值,我们就必须给注解赋值 @MyAnnotation1 ( name = "Daniel",age=18) public void test1(){ } @MyAnnotation2 ( "欢迎来到CSDN" ) public void test2(){ }}@interface MyAnnotation1{ //注解的参数:参数类型 + 参数名(); String name() default ""; int age() ; int id() default -1;//如果默认值为-1,则判定为不存在 String [] school() default ("深圳市福田区");}@interface MyAnnotation2{ String value();}
2.3 元注解
** * @author Daniel * 元注解 */@MyAnnotion//public class YuanZhuJie{ @MyAnnotion//方法注解 public void test(){ }}//@Retention ( value = RetentionPolicy.CLASS)//Retention 表示我们的注解在哪些地方还有效@Retention ( value = RetentionPolicy.RUNTIME) //点击注解—>看源码//Target 表示我们的注解可以用在哪些地方@Target ( value = {ElementType.TYPE,ElementType.METHOD})//类注解和方法注解 TYPE 类注解 METHOD 方法注解@Documented //表示是否将我们的注解生成在Javadoc中@Inherited//子类可以继承父类的注解@interface MyAnnotion{}
二、反射
2.1 Java反射机制概述
1、java反射:在程序运行过程中,可以对任意一个类型进行任意的操作。例如:加载任意类型、调用类型的任意方法、获取任意的成员变量、构造方法,可以创建该类型的对象。
2、对于任意一个对象,都能调用这个对象的任意一个方法【不知道要使用什么类型】
3、如果要获取一个类型的各种内容,首先要获取这个类的字节码对象
4、解剖这个类型,获取类中的成员,需要使用Class类型中定义的方法
5、这种【动态】获取信息以及【动态】访问成员的这种方式,称为:反射
反射的举例:
房屋设计图纸---->实体房屋,反射:有了房屋,获取设计图纸
汽车设计图纸---->实体汽车,反射:有了汽车,获取设计图纸
无论是房屋设计图纸,还是汽车的设计图纸,都是图纸:抽取一个图纸类型
/ * @author Daniel * 反射 */public class FanSheDaniel extends Object{ //什么是反射 public static void main(String[] args) throws Exception { //通过反射获取类的Class对象 Class c1 = Class.forName ( "cn.Person" ); Class c2 = Class.forName ( "cn.Person" ); Class c3 = Class.forName ( "cn.Person" ); Class c4 = Class.forName ( "cn.Person" ); System.out.println ( c1 ); //一个类在内存中只有一个class对象 //一个类被加载后,类的整个结构都会被封装在Class对象中 System.out.println ( c1.hashCode () ); System.out.println ( c2.hashCode () ); System.out.println ( c3.hashCode () ); System.out.println ( c4.hashCode () ); }}//实体类:pojo,entityclass Person{ private String name; private int age; private int id; public Person() { } public Person(String name, int age, int id) { this.name = name; this.age = age; this.id = id; } 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; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; }}
运行结果为:
2.1.1 反射机制与应用
2.1.2 反射的优点和缺点
2.1.3 反射相关的主要API
2.2 理解Class类并获取Class实例
2.2.1 Class类的常用方法
2.2.2 获取Class类的实例
/ * @author Daniel * 获取对象的方式 */public class FanSheDemo1 { public static void main(String[] args) throws ClassNotFoundException { Person1 person1 = new Student(); System.out.println ("我是"+person1.name); //方式一:通过对象获得 Class c1 = person1.getClass (); System.out.println ( c1 ); //方式二:forname获得 Class c2 = Class.forName ( "cn.Student" ); System.out.println (c2); //方式三:通过类名.class获得 Class<Student> c4 = Student.class; System.out.println ( c4 ); //方式四:基本内置类型的包装都有一个type属性 Class<Integer> c5 = Integer.TYPE; System.out.println (c5); //获得父类类型 Class c6 = c1.getSuperclass (); System.out.println (c6); }}class Person1{ public String name; public Person1() { } public Person1(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person1{" + "name='" + name + '\'' + '}'; }}class Teacher extends Person1{ public Teacher(String name) { super ( "老师" ); }}class Student extends Person1{ public Student() { } public Student(String name) { super ( "学生" ); }}
运行结果为:
2.2.3 哪些类型可以有Class对象
/ * @author Daniel * */public class FanSheDemo2 { public static void main(String[] args) { Class c1 = Object.class;//类 Class c2 = Comparable.class;//接口 Class c3 = String[].class;//一维数组 Class c4 = int[][].class;//二维数组 Class c5 = Override.class;//注解 Class c6 = ElementType.class;//枚举 Class c7 = Integer.class;//基本数据类型 Class c8 = void.class;//void Class c9 = Class.class; //class System.out.println (c1); System.out.println (c2); System.out.println (c3); System.out.println (c4); System.out.println (c5); System.out.println (c6); System.out.println (c7); System.out.println (c8); System.out.println (c9); //只要元素类型与维度一样,就是同一个class int[] a = new int[10]; int[] b = new int[100]; System.out.println (a.getClass ().hashCode ()); System.out.println (b.getClass ().hashCode ()); }}
运行结果显示为:
2.2.4 Java内存分析
2.3 创建运行时类的对象
2.3.1 了解类的加载过程
2.3.2 类的加载与ClassLoader的理解
/ * @author Daniel * java 内存模型分析 */public class JavaNeiCun { public static void main(String[] args) { A a = new A (); System.out.println (a.m); / * 1.加载到内存,会产生一个类对应class对象 * 2.链接,链接结束后m = 0; * 3.初始化 * { * System.out.println("A类静态代码块初始化"); * m = 300; * m = 100; * } * m= 100 */ }}class A{ static { System.out.println ("A类静态代码初始化"); m = 300; } static int m = 100; public A(){ System.out.println ("A类无参构造初始化"); }}
运行结果为:
2.3.3 什么时候会出现类初始化?
public class ChuShiHuaDemo5 { static { System.out.println ("main方法被加载"); } public static void main(String[] args) throws ClassNotFoundException { //1.主动引用 Son son = new Son (); System.out.println ( son.getClass ().hashCode () ); //反射也会产生主动引用// Class c1 = Class.forName ( "fanshe.son" ); //System.out.println (c1); //不会产生类的引用的方法 System.out.println (son.b); System.out.println (son.M); }}class Father{ static int b = 1; static { System.out.println ("父类被加载"); }}class Son extends Father{ static { System.out.println ("子类被加载"); } static int b = 10; static final int M = 1;//常量并不会引起父类和子类的初始化}
运行结果为:
2.4 类的加载与ClassLoader
2.4.1 类加载器的作用
package fanshe;/ * @author Daniel * 类加载器 */public class RelaxDemo5 { public static void main(String[] args) throws ClassNotFoundException { //获取系统类的加载器 ClassLoader sld = ClassLoader.getSystemClassLoader (); System.out.println ( sld ); //获取系统类加载器的父类加载器——>扩展类加载器 ClassLoader parent = sld.getParent (); System.out.println ( parent ); //获取扩展类加载器的父类加载器——>根加载器(c/c++) ClassLoader parent1 = parent.getParent (); System.out.println ( parent1 ); //测试当前类是哪个加载器加载的 ClassLoader cld = Class.forName ( "fanshe.RelaxDemo5" ).getClassLoader (); System.out.println ( cld ); //测试jdk内置的类是谁加载的 ClassLoader cld1 = Class.forName ( "java.lang.Object" ).getClassLoader (); System.out.println ( cld1 ); //如何获得类加载器加载的路径 System.out.println ( System.getProperty ( "java.class.path" ) ); / * D:\develop\jdk\jre\lib\charsets.jar; * D:\develop\jdk\jre\lib\deploy.jar; * D:\develop\jdk\jre\lib\ext\access-bridge-64.jar; * D:\develop\jdk\jre\lib\ext\cldrdata.jar; * D:\develop\jdk\jre\lib\ext\dnsns.jar; * D:\develop\jdk\jre\lib\ext\jaccess.jar; * D:\develop\jdk\jre\lib\ext\jfxrt.jar; * D:\develop\jdk\jre\lib\ext\localedata.jar; * D:\develop\jdk\jre\lib\ext\nashorn.jar; * D:\develop\jdk\jre\lib\ext\sunec.jar; * D:\develop\jdk\jre\lib\ext\sunjce_provider.jar; * D:\develop\jdk\jre\lib\ext\sunmscapi.jar; * D:\develop\jdk\jre\lib\ext\sunpkcs11.jar; * D:\develop\jdk\jre\lib\ext\zipfs.jar; * D:\develop\jdk\jre\lib\javaws.jar; * D:\develop\jdk\jre\lib\jce.jar; * D:\develop\jdk\jre\lib\jfr.jar; * D:\develop\jdk\jre\lib\jfxswt.jar; * D:\develop\jdk\jre\lib\jsse.jar; * D:\develop\jdk\jre\lib\management-agent.jar; * D:\develop\jdk\jre\lib\plugin.jar; * D:\develop\jdk\jre\lib\resources.jar; * D:\develop\jdk\jre\lib\rt.jar; * D:\develop\ideaIU-2018.2.5\idea_workspace\threadXian\out\production\threadXian; * D:\develop\ideaIU-2018.2.5\idea_workspace\threadXian\src\com\xiancheng\lib\commons-io-2.6.jar; * D:\develop\ideaIU-2018.2.5\idea\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar */ }}
运行结果为:
2.5 获取运行时类的完成结构
2.6有了Class对象能做什么呢?
2.7 调用运行时类的指定结构
2.7.1 调用指定的方法
SetAccessible
总结:
(1)在实际的操作中,取得类的信息的操作代码,并不会经常开发。
(2)一定要熟悉Java.lang.reflect包的作用,反射机制。
(3)如何取得属性、方法、构造器的名称,修饰符等。
2.8 反射操作泛型(了解)
2.9 反射操作注解
getAnnotations
getAnnotation
练习:ORM
了解什么是ORM?
Object relationship Mapping ———>对象关系映射
类和表结构对应
属性和字段对应
对象和记录对应
要求:利用注解和反射完成类和表结构的映射关系
package fanshe;import java.lang.annotation.*;import java.lang.reflect.Field;public class RelaxAnnotation { public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName ( "fanshe.Student1" ); //通过反射获得注解 Annotation[] annotations = c1.getAnnotations (); for (Annotation annotation : annotations) { System.out.println (annotation); } //获得注解的值value TableDaniel tableDaniel =(TableDaniel) c1.getAnnotation ( TableDaniel.class ); System.out.println ( tableDaniel.value () ); //获得指定类的注解 Field f = c1.getDeclaredField ( "name" ); FielDaniel annotation = f.getAnnotation ( FielDaniel.class ); System.out.println ( annotation.type () ); System.out.println ( annotation.columName () ); System.out.println ( annotation.length () ); }}@TableDaniel ( "db_student" )class Student1{ @FielDaniel (columName = "db_id",type = "int",length = 10) private int id; @FielDaniel (columName = "db_age",type = "int",length = 10) private int age; @FielDaniel (columName = "db_name",type = "varchar",length = 10) private String name; public Student1() { } public Student1(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student1{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; }}//类名的注解@Target ( ElementType.TYPE ) //type 类@Retention ( RetentionPolicy.RUNTIME )@interface TableDaniel{ String value();}//属性的注解@Target ( ElementType.FIELD )//Field 属性@Retention ( RetentionPolicy.RUNTIME )@interface FielDaniel{ String columName(); String type(); int length();}
运行结果为:
对应视频