反射的概念;类的加载器.

 

 

 

 

一、反射的概述:

 

 

1、基本概述:

(1)、(Class类)创建clazz对应的运行时类Person类的对象:

Class clazz=Person.class;

解析:clazz:栈空间的引用 ; Person.class:堆空间的一个实体,这样写之后Person类中的所有内容都可以引用。

(2)、(Field类)使用反射机制操作运行时类的指定属性:

    ①、调用public类型的属性

        Field f1=clazz.getField("name");//通过反射的方式获取name属性

        f1.set(p,"LiDeHua");//p对象的name属性改为"LiuDeHua"

        System.out.println(p);

    ②、调用非public类型的属性

        Field f2=clazz.getDeclaredField("age");

        f2.setAccessible(true);

        f2.set(p, 23);

        System.out.println(p);

(3)、(Method类)通过反射调用运行时类的指定的方法,方法名后不加小括号

    ①、用反射调用无参的方法

        Method m1=clazz.getMethod("show");

        //m1.invoke(p, args)//args用来书写类中方法的形参

        m1.invoke(p);//如果没有形参可省略第二位。

    ②、用反射调用有参的方法

        Method m2=clazz.getMethod("nation",String.class);

//对于有参的方法,需要在方法名后加上形参的类型,有几个参数就加几个类型。

        m2.invoke(p, "China");

 

2、Class类:

 

 

 

(1)、反射的概念了解:

反射:原来java程序是通过运行时类来找到类的属性和方法;现在是倒过来的,通过一个类对象来找类进而找类内部的属性、方法。

 

 (2)、 java.lang.Class:是反射的源头。

      我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成).class文件,

      .class文件加载到内存以后,就是一个运行时类,存在在缓存区,那么这个运行时类本身就是一个Class的实例!

      

      1、每一个运行时类只加载一次!

      2、有了Class的实例以后我们才可以进行如下的操作:

           1*)、创建对应的运行时类的对象

           2)、获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解.......)

           3*)、调用对应的运行时类的指定的结构(属性、方法、构造器)

           4)、反射的应用:动态代理

 

 

 (3)、如何获取Class的实例(3种)

    @Test

    public void testReflection() throws ClassNotFoundException{

        //1、调用运行时类本身的.class属性   如果没有Person类的话编译时就会报错

        Class clazz1=Person.class; //①、自定义的类的.class属性

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

       

        Class clazz2=String.class; //②、系统类的.class属性

       

        //2、通过运行时类的对象获取。通过此方法,体会一下反射的动态性。

        Person p1=new Person();//根据传进来的对象的不同,造的对象不同(newInstance造的对象)

        Class clazz3=p1.getClass();//创建clazz4的一个实例。

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

       

        //3、通过Class的静态方法获取     运行时才会报错

        String className="com.atguigu.fanshe.Person";

        Class clazz4=Class.forName(className);

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

        //4(了解)通过类的加载器

        ClassLoader classLoadar=this.getClass().getClassLoader();

        Class clazz5=classLoadar.loadClass(className);

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

    }

 

总代码:

package com.atguigu.fanshe;

import java.lang.reflect.Field;

import java.lang.reflect.Method;



import org.junit.Test;



public class TestReflection {

    //如何获取Class的实例(3种)

    @Test

    public void testReflection() throws ClassNotFoundException{

        //1、调用运行时类本身的.class属性

        Class clazz1=Person.class; //①、自定义的类的.class属性

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

       

        Class clazz2=String.class; //②、系统类的.class属性

        System.out.println(clazz2);

       

        //2、通过运行时类的对象获取

        Person p1=new Person();

        Class clazz3=p1.getClass();

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

       

        //3、通过Class的静态方法获取。通过此方法,体会一下反射的动态性。

        String className="com.atguigu.fanshe.Person";//根据传进来的对象的不同,造的对象不同(用newInstance造的对象)。

        Class clazz4=Class.forName(className);

//      clazz4.newInstance(); //创建clazz4的一个实例。

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

       

        //4、(了解)通过类的加载器

        ClassLoader classLoadar=this.getClass().getClassLoader();

        Class clazz5=classLoadar.loadClass(className);

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

    }

   


   

    /*

     * java.lang.Class:是反射的源头。

     * 我们创建了一个类,通过编译(javac.exe),生成对应的.class文件。之后我们使用java.exe加载(JVM的类加载器完成)此.class文件,

     * 此.class文件加载到内存以后,就是一个运行时类,存在在缓存区,那么这个运行时类本身就是一个Class的实例!

     *

     * 1、每一个运行时类只加载一次!

     * 2、有了Class的实例以后我们才可以进行如下的操作:

     *      1*)、创建对应的运行时类的对象

     *      2)、获取对应的运行时类的完整结构(属性、方法、构造器、内部类、父类、所在的包、异常、注解.......)

     *      3*)、调用对应的运行时类的指定的结构(属性、方法、构造器)

     *  4)、反射的应用:动态代理

     * */

    @Test

    public void testReflection3() {

         Person p=new Person();

         Class clazz=p.getClass();//通过运行时类的对象,调用其getClass()方法,返回其运行时类。(用这个getClass()方法来知道p来自于哪个类。)

    }

   

   

   

    //有了反射,可以通过反射创建一个类的对象,并调用其中的结构

    @Test

    public void testReflection2() throws Exception{

        Class clazz1=String.class;//类.class。

        Class<Person> clazz=Person.class;//默认是Object类型,如果想改类型需要在Class后加"<类型>"

/*    clazz:栈空间的引用 ;  Person.class:堆空间的一个实体*/

         

//1、创建clazz对应的运行时类Person类的对象

        Person p=(Person)clazz.newInstance();

        System.out.println(p);

//2、通过反射调用运行时类的指定的属性:

        //(1)、调用public类型的属性

        Field f1=clazz.getField("name");//通过反射的方式获取name属性

        f1.set(p,"LiDeHua");//将p对象的name属性改为"LiuDeHua"

        System.out.println(p);

        //(2)、调用非public类型的属性

        Field f2=clazz.getDeclaredField("age");

        f2.setAccessible(true);

        f2.set(p, 23);

        System.out.println(p);

//3、通过反射调用运行时类的指定的方法,方法名后不加小括号。

        //(1)、用反射调用无参的方法

        Method m1=clazz.getMethod("show");

//      m1.invoke(p, args)//args用来书写类中方法的形参

        m1.invoke(p);//如果没有形参可省略第二位。

        //(2)、用反射调用有参的方法

        Method m2=clazz.getMethod("nation",String.class);//对于有参的方法,需要在方法名后加上形参的类型,有几个参数就加几个类型。

        m2.invoke(p, "China");//

       

    }



   
   

    //没有反射的,如何创建一个类的对象,并调用其中的属性方法。

    @Test

    public void testReflection1() {

        Person p=new Person();

        p.setAge(23);

        p.setName("gg");

        p.show();

        p.nation("CN");

    }

}

 

总代码结束。

 

3、类的加载器

 

//4(了解)通过类的加载器

        ClassLoader classLoadar=this.getClass().getClassLoader();

        Class clazz5=classLoadar.loadClass(className);

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

 

 

public class TestReflection {

    //关于类的加载器

    @Test

    public void test5() throws ClassNotFoundException, IOException {

        ClassLoader loader1=ClassLoader.getSystemClassLoader();//系统的加载器

        System.out.println(loader1);

       

        ClassLoader loader2=loader1.getParent();

        System.out.println(loader2);

       

        ClassLoader loader3=loader2.getParent();

        System.out.println(loader3);



        Class clazz1=Person.class;

        ClassLoader loader4=clazz1.getClassLoader();

        System.out.println(loader4);

       

        String className="java.lang.String";

        Class clazz2=Class.forName(className);

        ClassLoader loader5=clazz2.getClassLoader();

        System.out.println(loader5);

       

        //掌握如下:

        //*****方法一、在具体的包里用下面的

//      ClassLoader loader=this.getClass().getClassLoader();

//      InputStream is=loader.getResourceAsStream("com\\atguigu\\java\\jdbc.properties");

//      Properties pros=new Properties();

//      pros.load(is);

//      String name=pros.getProperty("user");

//      System.out.println(name);

//     

//      String password=pros.getProperty("password");

//      System.out.println(password);

       

        //******方法二、在一个目录下用下面的

        FileInputStream is=new FileInputStream(new File("jdbc1.properties"));

       

        Properties pros=new Properties();

        pros.load(is);

        String name=pros.getProperty("user");

        System.out.println(name);

       

        String password=pros.getProperty("password");

        System.out.println(password);


    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值