Java8——反射机制

反射机制的认识:

"反":就是指可以利用对象找到对象的出处;

  • 取得class对象:public final Class<?> getClass()

范例:观察反

public class test {
	public static void main(String args[]) throws Exception {
		Date date = new Date();
		System.out.println(date.getClass()); // class java.util.Date
	}
}

getClass找到了这个类的完整名称;

Class类对象的实例化:

java.lang.Class是一个类,这个类是反射操作的源头,即:所有的类都要从此类开始进行;有3种实例化方式:

  • 调用Object类中的getClass()方法;(几乎很少用
public class test {
	public static void main(String args[]) throws Exception {
		Date date = new Date();
		Class<?> cls = date.getClass();
		System.out.println(cls); // class java.util.Date
	}
}
  • 使用 "类.class" 取得;(用于Hibernate、MyBatis、Spring)
public class test {
	public static void main(String args[]) throws Exception {
		Class<?> cls = Date.class;
		System.out.println(cls); // class java.util.Date
	}
}

之前是在类产生了实例化之后调用class类对象,这种方式并没有实例化对象就直接调用了;

  • 调用Class类一个方法

        |- public static Class<?> forName(string className) throws ClassNotFoundException;

public class test {
	public static void main(String args[]) throws Exception {
		Class<?> cls = Class.forName("java.util.Date");
		System.out.println(cls); // class java.util.Date
	}
}

此时可以不用import导入一个明确的类,而类名称是用string的形式进行描述;

反射实例化对象:

范例:利用反射实例化对象

package com.sunny.work;

class Book {
	public Book() {
		System.out.println("*************");
	}

	@Override
	public String toString() {
		return "这是一本书!";
	}
}

public class test {
	public static void main(String args[]) throws Exception {
		Class<?> cls = Class.forName("com.sunny.work.Book");
		Object obj = cls.newInstance(); // 使用new调用无参构造
		Book book = (Book) obj;
		System.out.println(book);

	}
}

有了反射之后,对象实例化可以不仅仅使用关键字 new ,可以使用反射进行对象实例化,但是这不意味 new 被完全取代了;

在任何程序中,new 是造成耦合的最大元凶;例如:工厂设计模式吃水果的例子,如果一开始只有一个水果苹果,需要一个new来实例化进而输出 "吃苹果" ,现在又加了一个橘子类要输出 "吃橘子" ,按理来说要再写一个橘子类,if else用到 equals 进行判断匹配,这时候只要新增一个类就要重写工厂类,但是如果使用反射,只是根据传入的类名进行取得,所以不必每次更改工厂类的代码;完成了解耦合操作,可扩展性十分强。

调用构造方法:

范例:调用有参构造

package com.sunny.work;

import java.lang.reflect.Constructor;

class Book {
	private String title;
	private double price;

	public Book(String title, double price) {
		this.title = title;
		this.price = price;
	}

	@Override
	public String toString() {
		return "书名:" + this.title + ", 价格:" + this.price;
	}
}

public class test {
	public static void main(String args[]) throws Exception {
		Class<?> cls = Class.forName("com.sunny.work.Book");
		Constructor<?> con = cls.getConstructor(String.class, double.class);    //类名
		Object obj = con.newInstance("Java开发", 79.8);
		System.out.println(obj);

	}
}

所以说,不管Java里面有多少构造方法,请至少保留一个无参构造,有参构造太麻烦了;

调用普通方法:

类中的普通方法只有在实例化对象之后才可以调用,并且实例化对象的方式有3种:new、克隆、反射;

范例:反射调用方法
 

package com.sunny.work;    //title.java

class Book {
	private String title;

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}
}
package com.sunny.work;    //test.java

import java.lang.reflect.Method;

public class test {
	public static void main(String args[]) throws Exception {
		String fieldName = "title"; // 要操作的成员
		Class<?> cls = Class.forName("com.sunny.work.Book");
		Object obj = cls.newInstance();    //必须给出实例化对象
		Method setMet = cls.getMethod("set" + initcap(fieldName), String.class);
		Method getMet = cls.getMethod("get" + initcap(fieldName));
		setMet.invoke(obj, "Java开发"); // 等价于Book类中的setTitle方法
		System.out.println(getMet.invoke(obj));
	}

	public static String initcap(String str) {
		return str.substring(0, 1).toUpperCase() + str.substring(1); // 首字母转大写操作
	}
}

此时完全看不到具体的操作类型,也就是说利用反射可以实现任意类的指定方法的调用;

反射调用成员:

类中的属性一定是在本类实例化对象之后才可以分配内存空间;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值