Java基础学习--第二弹

目录

一、作用域

二、Java创建对象的方式

三、反射机制

1. 通过反射得到Class类的三种方式

2. 通过反射获取构造器

3. 获取成员变量并调用

4. 通过反射获取成员方法

5. 反射的应用场景


一、作用域

作用域同类同包子类不同包
public
protected
friendly
private

二、Java创建对象的方式

        1. 通过new语句实例化一个对象

        2. 通过反射机制创建对象

        3. 通过clone()方法创建一个对象

        4. 通过反序列化的方式创建对象


三、反射机制

        反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,他不需要事先(写代码的时候或编译期)知道运行对象是谁。

        反射机制提供的功能主要有:

        (1)得到一个对象所属类

        (2)获得一个类的所有成员变量和方法

        (3)在运行时创建对象

        (4)在运行时调用对象的方法

1. 通过反射得到Class类的三种方式

public class ClassTest {
    public static void main(String[] args) {
        // 方法1
        Student stu = new Student();
        Class c1 = stu.getClass();
        System.out.println(c1.getName());
        // 方法2
        Class c2 = Student.class;
        System.out.println(c1 == c2);
        // 方法3
        try {
            Class c3 = Class.forName("JavaBase.Student");
            System.out.println(c1 == c3);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

// JavaBase.Student
// true
// true

        通常情况下,会使用第三种方式获取类信息,原因如下:第一种已经创建出了Student实例,已经失去了反射的意义;第二种需要导入相应类的包,不导包就会编译错误;第三种可以使用字符串,也可以将该字符串写在配置文件中。

2. 通过反射获取构造器

package JavaBase;

import java.lang.reflect.Constructor;

public class ClassTest {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("JavaBase.Student");

        System.out.println("********所有公有构造器********");
        Constructor[] conArr = cls.getConstructors(); // 获取所有公有构造器
        for(Constructor c : conArr){
            System.out.println(c);
        }

        System.out.println("********所有构造器********");
        conArr = cls.getDeclaredConstructors(); // 获取所有构造器包括私有、受保护等修饰符修饰的
        for(Constructor c : conArr){
            System.out.println(c);
        }

        System.out.println("********所有公有、无参构造器********");
        // 因为是无参构造器,所以类型是null,也可以不写(括号里填的是参数类型)
        // 返回的是描述这个无参构造器的类对象
        Constructor constructor = cls.getConstructor(null);
        System.out.println("constructor = " + constructor);

        Object obj = constructor.newInstance(); // 调用构造器,创建对象
        Student student = (Student) obj;
        student.setAge(18);
        System.out.println(student.getAge());

        System.out.println("********所以私有构造器,并调用********");
        constructor = cls.getDeclaredConstructor(String.class);
        System.out.println(constructor);
        constructor.setAccessible(true); // 暴力访问(忽略访问修饰符)
        obj = constructor.newInstance("Jay");
        obj.toString();
    }
}

class Student{
    private String name;
    private int age;
    public char sex;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("这是一个有参构造器");
    }

    public Student() {
        System.out.println("这是一个无参构造器");
    }

    private Student(String name){
        this.name = name;
        System.out.println("这是一个私有构造器");
    }

    protected Student(int age) {
        this.age = age;
        System.out.println("这是一个受保护的构造器");
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3. 获取成员变量并调用

public class ClassTest {
    public static void main(String[] args) throws Exception {
        Class cls = Class.forName("JavaBase.Student");

        System.out.println("********所有公有字段********");
        Field[] fields = cls.getFields(); // 获取字段
        for(Field f : fields){
            System.out.println(f);
        }

        System.out.println("********所有字段********");
        fields = cls.getDeclaredFields(); // 获取所有字段包括私有、受保护等修饰符修饰的
        for(Field f : fields){
            System.out.println(f);
        }

        System.out.println("********所有公有字段,并调用********");
        Field f = cls.getField("sex");
        System.out.println(f);

        Object obj = cls.getConstructor().newInstance(); // 调用构造器,创建对象
        Student student = (Student) obj;
        f.set(obj,'男'); // 为sex这个属性赋值
        System.out.println(student.sex);

        System.out.println("********所以私有字段,并调用********");
        f = cls.getDeclaredField("name");
        f.setAccessible(true);
        f.set(obj,"Jay");
        System.out.println(student);
    }
}

4. 通过反射获取成员方法

        原理同上,只是调用的方法和返回值类型不同 

Method[] methods = cls.getMethods();
        Method method = cls.getMethod("newName",String.class);
        method = cls.getDeclaredMethod("newAge", int.class);

5. 反射的应用场景

        1. 逆向代码,如反编译

        2. 与注解相结合,如Retrofit

        3. 单纯的反射机制应用框架,如EventBus 2.x

        4. 动态生成类框架,如Gson

Java的反射机制在平时的业务开发过程中很少使用到,但是在一些基础框架的搭建上应用非常广泛

        

        

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值