java访问修饰符及反射使用

一、访问修饰符

1、添加

	public:全部可见
	private:本类可见
	protected:子类可见
	defult:包类可见

2、不添加

默认protected:对当前包开放

二、反射

1、什么是反射

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制

2、使用步骤

  1. 获得你想操作的类的java.lang.Class对象。在运行中的Java程序中,用java.lang.Class类来描述类和接口等。
  2. 调用诸如getDeclaredMethods的方法,取得该类中定义的所有方法的列表。
  3. 使用反射的API来操作这些信息。

3、获取Class对象的三种方式

  1. 过对象的getClass方法进行获取。这种方式需要具体的类和该类的对象,以及调用getClass方法。
  2. 任何数据类型(包括基本数据类型)都具备着一个静态的属性class,通过它可直接获取到该类型对应的Class对象。这种方式要使用具体的类,然后调用类中的静态属性class完成,无需调用方法,性能更好
  3. 通过Class.forName()方法获取。这种方式仅需使用类名,就可以获取该类的Class对象,更有利于扩展。

4、api使用

1.使用java反射获取类的构造函数(公有、私有)(有参,无参)

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
 * 测试使用java反射获取类的构造函数并创建对象
 * @author Sunshine
 *
 */
public class ReflectPer {
    private static Class class1;
    //因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个测试方法中重复创建
    //注:@beforeclass在执行测试方法前运行
    @BeforeClass
    public static void beforeClass() throws Exception{
        System.out.println("====测试方法启动前先加载类====");
        class1 = Class.forName("myPractise.Per");//加载类
    }
    //获取类的公有无参构造函数,并创建对象
    @Test
    public void test1() throws Exception{
        Constructor constructor = class1.getConstructor(null);//获取公有无参构造器,值为null代表获取无参构造器
        Per per = (Per) constructor.newInstance(null);//创建对象,返回的是Object类型要强转
        System.out.println(per.name);//可以调用类的属性-----成功
    }
    //获取类的公有参构造函数,并创建对象
    @Test
    public void test2()throws Exception{
        Constructor constructor = class1.getConstructor(String.class,int.class);//获取公有多个参数构造器,参数为构造器中参数的类型
        Per per = (Per)constructor.newInstance("baby",24);//创建对象
    }
    //获取类的私有有参构造函数,并创建对象
    @Test
    public void test3()throws Exception{
        Constructor constructor = class1.getDeclaredConstructor(String.class);//获取公有多个参数构造器,参数为构造器中参数的类型
        constructor.setAccessible(true);//暴力反射,只有将属性设置为true才可以创建对象
        Per per = (Per)constructor.newInstance("baby");
        System.out.println(per.weight);//可以调用类的属性-----成功
        //注:通常情况下一个类不可以访问另一个类的私有的属性,方法。。但是通过java反射可以
    }
    @AfterClass
    public static void afterClass(){
        System.out.println("===测试完成将对象赋值为null===");
    }
}

2.使用java反射获取类的方法(公有、私有)(有参,无参)

 import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
/**
 * 测试使用java反射获取类方法
 * @author Sunshine
 *
 */
public class ReflectPer {
    private static Class class1;
    private static Per per;
    //因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个方法中重复创建
    //注:@beforeclass在执行测试方法前运行
    @BeforeClass
    public static void beforeClass() throws Exception{
        System.out.println("====测试方法启动前先加载类====");
        class1 = Class.forName("myPractise.Per");//加载类
        per = (Per) class1.getConstructor(null).newInstance(null);//使用反射创建对象
    }
    
    //获取类的公有无参方法
    @Test
    public void test4()throws Exception{
        Method method = class1.getMethod("methodT1", null);//获取指定的方法,参数为方法名和该方法的参数类型,因为我们这是测试无参的方法,所以传入null
        method.invoke(per, null);//使用invoke方法来调用,参数为指定对象,该方法传入的参数,因为我们这是测试无参的方法,所以传入null
    }
    //获取类的公有有参方法
    @Test
    public void test5()throws Exception{
        Method method = class1.getMethod("methodT1", String.class,int.class);//获取指定的方法,参数为方法名和该方法的参数类型
        method.invoke(per, "sunshine",25);//使用invoke方法来调用,参数为指定对象,该方法传入的参数
    }
    @Test
    public void test6()throws Exception{
        Method method = class1.getDeclaredMethod("methodT1", String.class);//获取指定的方法,参数为方法名和该方法的参数类型
        method.setAccessible(true);//暴力反射,默认为false,未设置则调用类的私有方法不成功
        method.invoke(per, "sunshine");//使用invoke方法来调用,参数为指定对象,该方法传入的参数
        System.out.println(method.getReturnType());//获取到该类指定方法的返回值类型
    }
    @Test
    public void test7()throws Exception{
        Method method = class1.getMethod("methodT2", int[].class,String[].class);
        method.invoke(per, new int[]{1,2},new String[]{"AA","BB"});
    }
    //获取某个类的main方法比较特殊也可以说是只要传入的参数为单个数组特殊
    //jdk5之后新增特性--可变参数
    //在加载时会将传入的数组进行拆分,这样就会报错,java.lang.IllegalArgumentException: wrong number of arguments 错误的参数个数
    //这时候我们可以欺骗一下虚拟机,告诉他我们传入的是一个对象将new String[]{"AA","BB"}换成(Object)new String[]{"AA","BB"}
    @Test
    public void test8()throws Exception{
        Method method = class1.getMethod("main",String[].class);
        method.invoke(per,(Object)new String[]{"AA","BB"});
    }
    @AfterClass
    public static void afterClass(){
        System.out.println("===测试完成将对象赋值为null===");
    }
}

3.使用java反射获取类的属性(公有、私有)

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * 测试使用java反射获取类的属性
 * 
 * @author Sunshine
 *
 */
public class ReflectPer {
    private static Class class1;
    private static Per per;

    // 因为java反射获取类时都需要加载类,在这里我就使用Junit的@beforeclass来去加载类,不用在每个测试方法中重复创建
    // 注:@beforeclass在执行测试方法前运行
    @BeforeClass
    public static void beforeClass() throws Exception {
        System.out.println("====测试方法启动前先加载类====");
        class1 = Class.forName("myPractise.Per");// 加载类
        per = (Per) class1.getConstructor(null).newInstance(null);// 使用反射创建对象
    }
    // 公有属性
    @Test
    public void test9() throws Exception {
        // 获取某个属性,参数是属性名
        Field field = class1.getField("name");
        // 输出属性值,需要传入指定对象
        System.out.println(field.get(per));
        // 获取属性的类型
        System.out.println(field.getType());
        // 获取多个属性
        Field[] field1 = class1.getFields();
        // 增强for循环Jdk1.5后的新特性,只适用于数组和实现了Iterator的集合
        for (Field str : field1) {
            System.out.println(str);
        }
        // 设置属性值
        field.set(per, "baby");
        System.out.println(field.get(per));
    }
    //私有属性
    @Test
    public void test10() throws Exception {
        Field field = class1.getDeclaredField("age");
        field.setAccessible(true);//暴力反射
        System.out.println(field.get(per));
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("===测试完成将对象赋值为null===");
    }
}

你可能感兴趣的:(java基础)