======================================================================
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";//指定属性的默认值.
}