一、访问修饰符
1、添加
public:全部可见
private:本类可见
protected:子类可见
defult:包类可见
2、不添加
默认protected:对当前包开放
二、反射
1、什么是反射
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制
2、使用步骤
- 获得你想操作的类的java.lang.Class对象。在运行中的Java程序中,用java.lang.Class类来描述类和接口等。
- 调用诸如getDeclaredMethods的方法,取得该类中定义的所有方法的列表。
- 使用反射的API来操作这些信息。
3、获取Class对象的三种方式
- 过对象的getClass方法进行获取。这种方式需要具体的类和该类的对象,以及调用getClass方法。
- 任何数据类型(包括基本数据类型)都具备着一个静态的属性class,通过它可直接获取到该类型对应的Class对象。这种方式要使用具体的类,然后调用类中的静态属性class完成,无需调用方法,性能更好
- 通过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===");
}
}