java是面向对象的编程语言,对象,是一种具体的概念
类:类是对具有相同特征或属性,具有相同行为能力的一类事物的描述或称呼
对象:对象是这一类事物带有属性值,具有具体行为的个体或实例
面向对象编程的语言
package test;
//定义一个类
public class Phone {
//添加一些属性
public String name;
public double weight;
//无参构造器
public Phone(){
}
//有参构造器
public Phone(String name,double weight){
this.name = name;
this.weight = weight;
}
//写入一些方法
public void dianyuan(){
System.out.println("开机");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
}
Java中的反射机制
反射允许对封装类的字段,方法和构造函数的信息进行编程访问。
反射允许对成员变量,成员方法和构造方法的信息进行编程访问
通俗点说,是从类里面拿东西,把成员变量,成员方法和构造方法获取出来(获取其所有信息)
获取是从class字节码文件中去获取的
反射获取class对象的三种方式
- Class.forName("全类名");
- 类名+class
- 对象+getClass();
三种方式分别对应三个阶段
public class phone_tes2 {
public static void main(String[] args) throws Exception{
//获取类
//1.使用class.forName()方法
//最为常用的
Class p = Class.forName("test.Phone");
//2.使用类的class方法
//一般更多的是当前参数进行传递
Class p3 = Phone.class;
//3.使用实例化对象的getClass()方法
//当我们已经有了这个类的对象时才使用
Phone p1 = new Phone();
Class p2 = p1.getClass();
}
}
反射获取构造方法
package test;
public class Phone {
public String name;
public double weight;
//无参构造器
public Phone(){
}
//有参构造器
public Phone(String name){
this.name = name;
}
protected Phone(double weight){
this.weight = weight;
}
private Phone(String name,double weight){
this.name = name;
this.weight = weight;
}
}
package test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
public class phone_tes3 {
public static void main(String[] args) throws Exception{
//1.获取class字节码文件对象
Class clazz = Class.forName("test.Phone");
//2.获取public构造方法
Constructor[] cons = clazz.getConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
//2.获取所有构造方法
Constructor[] cons2 = clazz.getDeclaredConstructors();
for (Constructor con : cons2) {
System.out.println(con);
}
//3.获取单个构造方法
Constructor con3 = clazz.getDeclaredConstructor(double.class);
System.out.println(con3);
Constructor con4 = clazz.getDeclaredConstructor(String.class,double.class);
//获取权限修饰符对应的数字
int modifiers = con4.getModifiers();
System.out.println(modifiers);
Parameter[] parameters = con4.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//暴力反射:临时取消权限校验(即可用私有的构造方法创建对象)
con4.setAccessible(true);
Phone iphone = (Phone) con4.newInstance("enya", 88891);
System.out.println(iphone);
}
}
反射获取成员变量
package test2;
public class Student {
private String name;
private int age;
public String gender;
public Student(){
}
public Student(String name,int age,String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
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;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
package test2;
import java.lang.reflect.Field;
public class ste_tes1 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
//1.获取class字节码文件的对象
Class clazz = Class.forName("test2.Student");
//2.获取所有的成员变量
Field[] Fields = clazz.getDeclaredFields();
for (Field field : Fields) {
System.out.println(field);
}
//获取单个成员变量
Field name = clazz.getDeclaredField("name");
System.out.println(name);
//获取权限修饰符
int modifiers = name.getModifiers();
System.out.println(modifiers);
//获取成员变量名
String name1 = name.getName();
System.out.println(name1);
//获取成员变量数据类型
Class<?> type = name.getType();
System.out.println(type);
//获取成员变量记录的值
Student s = new Student("ENYA",19,"女");
name.setAccessible(true);
String value = (String) name.get(s);
System.out.println(value);
//修改对象里面记录的值
name.set(s,"Iris");
System.out.println(s.getName());
}
}
反射获取成员方法
package test2;
import java.io.IOException;
public class Student {
private String name;
private int age;
public Student(){
}
public Student(String name,int age,String gender){
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;
}
public void sleep(){
System.out.println("睡觉");
}
private String eat(String somethimg)throws IOException,NullPointerException,ClassCastException {
System.out.println("在吃"+somethimg);
return "yummy!!";
}
}
package test2;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class ste_tes2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
//1.获取class字节
Class clazz = Class.forName("test2.Student");
//2.获取所有方法对象(包含父类中所有的公共方法)
// Method[] methods = clazz.getMethods();
// for (Method method : methods) {
// System.out.println(method);
// }
//2.获取所有方法对象(不能获取父类的,但是可以获取本类中私有的方法)
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
//获取指定的单一方法
Method m = clazz.getDeclaredMethod("eat", String.class);
System.out.println(m);
//获取方法的修饰符
int modifiers = m.getModifiers();
System.out.println(modifiers);
//获取方法的名字
String name = m.getName();
System.out.println(name);
//获取方法的形参
Parameter[] parameters = m.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter);
}
//获取方法抛出的异常
Class<?>[] exceptionTypes = m.getExceptionTypes();
for (Class<?> exceptionType : exceptionTypes) {
System.out.println(exceptionType);
}
//方法运行
Student s = new Student();
m.setAccessible(true);
//参数一表示方法的调用者,参数二表示在调用方法的时候传递的实际参数
Object result = m.invoke(s, "汉堡包");
System.out.println(result);
}
}
练习
保存信息
对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
package test3;
public class Phone {
public String name;
public double weight;
//无参构造器
public Phone(){
}
//有参构造器
public Phone(String name){
this.name = name;
}
protected Phone(double weight){
this.weight = weight;
}
Phone(String name, double weight){
this.name = name;
this.weight = weight;
}
public void dianyuan(){
System.out.println("开机");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
}
package test3;
import java.io.IOException;
public class Student {
private String name;
private int age;
public String gender;
public Student(){
}
public Student(String name, int age, String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
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;
}
public void sleep(){
System.out.println("睡觉");
}
private String eat(String somethimg)throws IOException,NullPointerException,ClassCastException {
System.out.println("在吃"+somethimg);
return "yummy!!";
}
}
package test3;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
public class demo1 {
public static void main(String[] args) throws IllegalAccessException, IOException {
Student s = new Student("enya",19,"女");
Phone t = new Phone("apple",1987);
saveobject(s);
}
//把对象里面所有的成员变量名和值保存到本地文件中
public static void saveobject(Object obj) throws IllegalAccessException, IOException {
//1.获取字节码文件的对象
Class clazz = obj.getClass();
//创建IO流
BufferedWriter bw = new BufferedWriter(new FileWriter("demo1\\a.txt"));
//2.获取所有的成员变量
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
//获取成员变量的名字
String name = field.getName();
// System.out.println(name);
//获取成员变量的值
Object value = field.get(obj);
//写入数据
bw.write(name + "=" + value);
bw.newLine();
}
bw.close();
}
}
运行结果:
name=enya
age=19
gender=女
跟配置文件结合动态创建
反射可以跟配置文件结合的方式,动态创建对象,并调用方法
package test4;
public class Phone {
public String name;
public double weight;
//无参构造器
public Phone(){
}
//有参构造器
public Phone(String name){
this.name = name;
}
protected Phone(double weight){
this.weight = weight;
}
Phone(String name, double weight){
this.name = name;
this.weight = weight;
}
public void dianyuan(){
System.out.println("手机正在开机");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setWeight(double weight) {
this.weight = weight;
}
public double getWeight() {
return weight;
}
}
package test4;
import java.io.IOException;
public class Student {
private String name;
private int age;
public String gender;
public Student(){
}
public Student(String name, int age, String gender){
this.name = name;
this.age = age;
this.gender = gender;
}
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;
}
public void sleep(){
System.out.println("学生正在睡觉");
}
}
classname=test4.Phone
method=dianyuan
package test4;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class demo {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
/*
反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
*/
//1.读取配置文件中的信息
Properties prop = new Properties();
FileInputStream fis = new FileInputStream("demo1\\prop.properties");
prop.load(fis);
fis.close();
System.out.println(prop);
//2.获取全类名和方法名
String classname = (String) prop.get("classname");
String methodname = (String) prop.get("method");
System.out.println(classname);
System.out.println(methodname);
//3.利用反射创建对象并运行方法
Class clazz = Class.forName(classname);
// Method m = clazz.getDeclaredMethod(methodname);
// Student s = new Student();
// m.setAccessible(true);
// Object o = m.invoke(s);
// System.out.println(o);
//获取构造方法
Constructor con = clazz.getDeclaredConstructor();
Object o = con.newInstance();
System.out.println(o);
//获取成员变量并运行
Method method = clazz.getDeclaredMethod(methodname);
method.setAccessible(true);
method.invoke(o);
}
}