======================================================================
java 第十八天 : 反射 , 注释
======================================================================
java 第十八天 : 反射 , 注释
======================================================================
(1)
反射
:
做通用编码
,
避免不用硬编码
.
Class : 这个类的类 , 叫做类对象 , 封装了类而信息 .
类对象 , 存储虚拟机读到的类信息 .
Class : 这个类的类 , 叫做类对象 , 封装了类而信息 .
类对象 , 存储虚拟机读到的类信息 .
Class 类对象(封装类的信息)
例如Student.class Teacher.class 在虚拟机中
编译后.class文件为类的信息在JVM中的体现:
JVM
|
Student
|
Teacher
|
就像你逛动物园 , 你要看某些动物 , 你不认识它 , 会要看他旁边的说明 ( 牌子 ), 描述的是类信息 . 动物旁边的牌子 , 就像这个类的类对象 . 如果加上一个动物 , 就要作一个牌子来描述这个类 .
类对象 : new Class();
对象类 : Object
类类 : Class
对象对象 : new Object();
类 : 狼类 .
对象 : 类的对象,就是一只狼
类对象 : 牌子 , 狼对象的信息
类类 : 牌子类 .
(2) Field: FIeld 对象就封装了一个属性信息 .
(3) Method: 封装了类的方法信息 .
(4) Constructor: 封装了类的构造方法 .
如何获得一个类的类对象?有如下三种方法:
(1) Class c1=String
.class; //类名加.class
前提为知道类名
(2) Student s1=new Student(“Liucy”);
//通过类的对象得到类对象
Class c2=s1
.getClass(); //得到Student所属类的类对象
例如:
String s1=”123”;
String s2=”456”;
Class c1=s1.getClass();
Class c2=s2.getClass(); c1==c2的判断结果为true. 全类只有一个
类对象
最常见也最灵活的方式:
(3) String
className=”java.lang.String”; //用字符串当参数
Class c3=Class.forName(className); //静态方法。 会发生类加载
有可能此类未被加载,则要先加载(通过类名找到文件加载),再返回类对象
注意:
类名应写
全限定名。
即包名
+
类名
使用场合为类名存在字符串中时。
例子:
写一个程序,从命令行输入要查找的类,然后返回这个类的所有方法名。(从命令行输入的必需是
全限定名。即包名+类名
)
这些信息都封装了 , 在一个类对象里 .
package day18;
import java.lang.reflect.*;
public class TestRefelction {
public static void main(String[] args) throws Exception{
String s=new String("231");
String className=args[0];
String constructorParameter=args[1];
String methodName=args[2];
String methodParameter=args[3];
//java xx Student liucy study CoreJava
//java xx Teacher huxz teach CoreJava
Class c1=Class.forName(className);
//2. 获得想要调用的构造方法对象
Constructor con=c1.getConstructor(String.class);
//3. 调用构造方法 , 创建对象
Object o=con.newInstance(constructorParameter);
//4. 获得想要调用的方法对象
Method m=c1.getMethod(methodName,String.class);
//5. 对创建好的对象调用指定的方法 .
m.invoke(o,methodParameter);
}
}
class Student{
String name;
public Student(String name){
this.name=name;
}
public void study(String course){
System.out.println(name+" 学习了 "+course);
}
public void eat(String food){
System.out.println(name+" 吃 "+food);
}
}
class Teacher{
String name;
Teacher(String name){
this.name=name;
}
public void teach(String name){
System.out.println("teach "+name);
}
public void study(String course){
System.out.println(name+" 学 "+course);
}
}
------------------------------------------------------------------------------------------------------------------
(2)
注释
Annotation
(元数据)
<1> 描述代码的注释的文字 .
<2> 描述代码的代码
一个注释是一个类型 ,@Override 是一个类型 java.lang.
注释的类型 :
<1> @Override 如果没有属性 , 叫做 标记注释 @ 注释的名字
<2> 单值注释 , @ 注释名 (pa="123")/(pa=10) value( 属性名 ) : [value="abc"] @__("abc") 此时的 value 可以不写 .
<3> 多值注释 @ 注释名 (pa1=3,pa2="abc")
java 提供 3 种注释
@Override
@Deprecated
class // 表示这个类是过期的 . 编译器警告你
mothod // 表示方法是过期的 .
@SupressWarnigs(value="adsf") /SupressWarnigs("asdf") / SupressWarnigs({"asdf","adf","adsf"})// 数组的显示的初始化 ,SupressWarnigs("Deprecated "," 泛型 ") // 会抑制警告 .
(3) 自定义注释
package day18;
import java.lang.annotation.*;
// 用来表示这个注释能注释什么 ?
@Target(value={ElementType.CONSTRUCTOR,ElementType.METHOD})
// 表示这个注释保留到什么时候 .
@Retention(value=RetentionPolicy.SOURCE)
//sourse: .java 只是给编译器用的 , 编译器用完之后会舍弃掉 .
//class: 编译器会编译到 .class 文件中 , 但是类加载的时候会舍弃掉 .
//runtime: .class .java 都有 , 加载到虚拟机也不会舍弃掉 . 如果让注释有用的话必需让注释类型是 : runtime
//doucumented : 是否加到帮助文档中 .
//inherited: / 是否继承到子类中 .
public @interface TestCase {// 定义一个注释 , 是一个特殊的接口 . 是一个特殊的类
// 给这个注释添加注释
// 注释中的属性即是属性又是方法 .
//24 种类型属性可以注释
//8 种基本类型 , 字符串 (String), 枚举 (Enum), 注释 (Annotation),
// 类对象 (Class), 以及他们的数组 .
String parameter() default "liucy";// 指定属性的默认值 .
}
<1> 描述代码的注释的文字 .
<2> 描述代码的代码
一个注释是一个类型 ,@Override 是一个类型 java.lang.
注释的类型 :
<1> @Override 如果没有属性 , 叫做 标记注释 @ 注释的名字
<2> 单值注释 , @ 注释名 (pa="123")/(pa=10) value( 属性名 ) : [value="abc"] @__("abc") 此时的 value 可以不写 .
<3> 多值注释 @ 注释名 (pa1=3,pa2="abc")
java 提供 3 种注释
@Override
@Deprecated
class // 表示这个类是过期的 . 编译器警告你
mothod // 表示方法是过期的 .
@SupressWarnigs(value="adsf") /SupressWarnigs("asdf") / SupressWarnigs({"asdf","adf","adsf"})// 数组的显示的初始化 ,SupressWarnigs("Deprecated "," 泛型 ") // 会抑制警告 .
(3) 自定义注释
package day18;
import java.lang.annotation.*;
// 用来表示这个注释能注释什么 ?
@Target(value={ElementType.CONSTRUCTOR,ElementType.METHOD})
// 表示这个注释保留到什么时候 .
@Retention(value=RetentionPolicy.SOURCE)
//sourse: .java 只是给编译器用的 , 编译器用完之后会舍弃掉 .
//class: 编译器会编译到 .class 文件中 , 但是类加载的时候会舍弃掉 .
//runtime: .class .java 都有 , 加载到虚拟机也不会舍弃掉 . 如果让注释有用的话必需让注释类型是 : runtime
//doucumented : 是否加到帮助文档中 .
//inherited: / 是否继承到子类中 .
public @interface TestCase {// 定义一个注释 , 是一个特殊的接口 . 是一个特殊的类
// 给这个注释添加注释
// 注释中的属性即是属性又是方法 .
//24 种类型属性可以注释
//8 种基本类型 , 字符串 (String), 枚举 (Enum), 注释 (Annotation),
// 类对象 (Class), 以及他们的数组 .
String parameter() default "liucy";// 指定属性的默认值 .
}