java基础--可变参数,反射

1.泛型的擦除
泛型只存在于源代码阶段,当编译过后,编译文件中不存在泛型
2.可变参数
应用场景:当多个方法逻辑相同,但是参数不同的时候
可变参数的定义:数据类型…数组的名称
注意:可变参数需要写在方法的参数列表中,不能单独定义
在方法的参数列表中只能有一个可变参数
方法中参数列表的可变参数必须要放到最后test2(int a,int...num)

public class Testmap {
    public static void main(String[] args) {
        test1(10,20,30);
    }

    //遍历map的方式一
    public static void test1(int...num){
        //num可以看作一个数组,这个数组用来存储传递过来的参数
        int sum=0;
        for(int i=0;i<num.length;i++){
            sum +=num[i];           
        }
        System.out.println(sum);
    }

}

3、反射
应用在一些通用性比较高的代码中,比如框架,大多数框架是使用反射来实现的。
在框架开发中都是基于配置文件的开发,在配置文件中设置了类,可以通过反射来得到类中的所有内容,可以让类中的某个方法来执行
类中的所有内容:属性、没有参数的构造方法、有参数的构造方法,普通的方法
反射的原理:首先是把源文件编译成字节码文件,然后在jvm上运行,会把字节码文件使用类加载器加载到内存中,在java中会有一个类来对内存中的字节码文件有一个表达就是Class类,如果得到了这个Class类,就可以得到类中的所有内容。
使用反射首先要得到Class类,有三种方法:(1)、类名.class (2)、对象.getClass();(3)、使用class.forName(“类的路径,即包名加类名”);
得到类就得到了所有内容,而这些内容也有相应的类来表示。属性—Field,构造方法—Constructor,普通方法——Method。

获取一个类额实例,可以new,也可以不new,不使用new就是通过反射来获取。

public static void test1() throws Exception{
        //得到Class类
        Class c3 = Class.forName("cn.liqing.junit.Person");
        //得到Person类的实例
        Person p = (Person) c3.newInstance();

    }

有关操作,代码
Person.java

package cn.liqing.junit;

public class Person {
    //属性
    private String name;
    private int age;
    //构造方法
    public Person(){

    }
    //普通方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    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;
    }
}

TestFs.java

package cn.liqing.junit;

import java.lang.reflect.Constructor;

import org.junit.Test;

public class TestFs {

    public static void main(String[] args) throws Exception {
        //获取Class类,3种方式
        Class class1 = Person.class;
        Class class2 = new Person().getClass();
        //下面这种方式用的最多
        Class class3 = Class.forName("cn.liqing.junit.Person");


    }
    @Test
    //操作无参构造方法
    public  void test1() throws Exception{
        //得到Class类
        Class c3 = Class.forName("cn.liqing.junit.Person");
        //得到Person类的实例
        Person p = (Person) c3.newInstance();
        p.setName("liqing");
        System.out.println(p.getName());

    }
    @Test
    //操作无参构造
    public void test2() throws Exception{
        //得到Class类
        Class c4 = Class.forName("cn.liqing.junit.Person");
        c4.getConstructors();//获取所有的有参构造
        //使用获取一个有参构造的方法,需要传递的是一个可变参数,这里面需要传递的是有参数构造方法里面的参数类型
        //类型使用class形式传递
        Constructor cs = c4.getConstructor(String.class,int.class);
        //获取Person的实例,里面传的是与构造方法对应的参数
        Person p2 = (Person) cs.newInstance("liqing",20);
        System.out.println(p2.getName()+"--"+p2.getAge());
    }

@Test
    //操作属性
    public void test3(){
        //得到Class类
        try {
            Class c5 = Class.forName("cn.liqing.junit.Person");
            //c5.getDeclaredFields();//获取所有的属性
            Field field1 = c5.getDeclaredField("name");
            //获取Person实例
            Person p5 = (Person) c5.newInstance();
            //field中set表示为属性设置值,第一个参数是要设置值得实例,第二个要为属性设置的值
            //因为属性是私有的,所以需要设置,如果不设置,会出现错误
            field1.setAccessible(true);//设置私有的属性值也可以操作
            field1.set(p5, "liqing");
            //得到属性的值使用get(),里面传递的也是要获得的对象的实例
            System.out.println(field1.get(p5));

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    @Test
    //操作普通方法
    public void test4() throws Exception{
        //得到Class
        Class c6 = Class.forName("cn.liqing.junit.Person");
        //得到Person实例
        Person p6 = (Person) c6.newInstance();
        //得到普通方法
        //c6.getDeclaredMethods();//得到所有的普通方法
        //下面这个方法里要传递的第一个是要操作的普通方法名称,第二个是要操作的方法里的参数的类型,使用class形式
        //如果要操作的方法是私有的,需要设置下面代码
        field1.setAccessible(true);
        Method m6 = c6.getDeclaredMethod("setName",String.class);
        //Method中有一个方法,是设置值,并执行这个方法,第一个参数值要操作的对象的实例,第二个是要为方的参数设置的值
        m6.invoke(p6, "liqing");
        System.out.println(p6.getName());
    }


}

当操作的方法是静态方法时,因为静态方法的调用的方式是类名.方法名,不需要类的实例,
使用反射操作时不需要静态实例,在invoke方法中的第一个参数里写null,m1.invoke(null,”liqing”)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值