可变参数
从JDK 5开始,java允许为方法定义长度可变的参数。
语法:
public void foo(int...args){}
注意事项:
调用可变参数的方法时,编译器将自动创建一个数组保存传递给方法给方法的可变参数,因此
程序员可以在方法体中以数组的形式访问可变参数
可变参数只能处于参数列表的最后,所以一个方法最多只能有一个长度可变的参数
反射
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。
Field类—可访问类的属性
Method类—可调用类的方法
Constructor类—可调用类的构造方法
反射常用的Java 类型
Class类—可获取类和类的成员信息Field类—可访问类的属性
Method类—可调用类的方法
Constructor类—可调用类的构造方法
使用反射的步骤:
1.导入java.lang.reflect.*
2.获得需要操作的类的Java.lang.Class对象
3.调用Class的方法获取Field、Method等对象
4.使用反射API进行操作 (设置属性﹑调用方法)
2.获得需要操作的类的Java.lang.Class对象
3.调用Class的方法获取Field、Method等对象
4.使用反射API进行操作 (设置属性﹑调用方法)
Class类
Class类是Java 反射机制的起源和入口
每个类都有自己的Class 对象
用于获取与类相关的各种信息
提供了获取类信息的相关方法
Class类继承自Object类
每个类都有自己的Class 对象
用于获取与类相关的各种信息
提供了获取类信息的相关方法
Class类继承自Object类
Class类存放类的结构信息
类名
父类﹑接口
方法﹑构造方法﹑属性
注释
类名
父类﹑接口
方法﹑构造方法﹑属性
注释
案例:
需求:
定义Student 类,包含:姓名和年龄等属性,有参和无参构造方法,输出所有信息的方法
使用多种方法生成一个Student类的Class对象
使用Class类获取Student类的结构信息并输出
通过有参(无参)构造方法动态创建Student类的对象
使用多种方法生成一个Student类的Class对象
使用Class类获取Student类的结构信息并输出
通过有参(无参)构造方法动态创建Student类的对象
package com.qf.day30_2;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 如何获取类的类对象
* @author wgy
*
*/
public class Demo1 {
public static void main(String[] args) throws Exception{
//getClassDemo();
// getContructor();
getMethod();
}
/**
* 获取类的类对象
*/
public static void getClassDemo() throws Exception{
//1 使用对象的getClass()
// Person zhangsan=new Person();
// Class c1= zhangsan.getClass();
// System.out.println(c1.hashCode());
//
// //2使用类的class属性
// Class c2=Person.class;
// System.out.println(c2.hashCode());
//3使用Class.forName方法
Class c3=Class.forName("com.qf.day30_2.Person");
System.out.println(c3.hashCode());
}
/**
* 获取构造方法
* @throws Exception
*/
public static void getContructor() throws Exception{
//1获取类对象
Class c3=Class.forName("com.qf.day30_2.Person");
//System.out.println(c3.hashCode());
//2获取构造方法
// Constructor[] cons=c3.getConstructors();
// for (Constructor c : cons) {
// System.out.println(c);
// }
//3获取一个构造方法
Constructor c=c3.getConstructor(null);
Constructor c2=c3.getConstructor(String.class,int.class,String.class);
Object person=c.newInstance(null);
Object person2=c2.newInstance("李四",20,"男");
System.out.println(person);
System.out.println(person2);
}
/**
* 获取方法
*/
public static void getMethod() throws Exception{
//1获取类对象
Class c1=Class.forName("com.qf.day30_2.Person");
//2获取方法
// Method[] methods=c1.getMethods(); //可以获取公开的方法,包含从父类继承的方法
// Method[] methods2=c1.getDeclaredMethods(); //获取类中所有的方法,不包含父类继承的
// for (Method m : methods2) {
// System.out.println(m);
// }
//3获取公开无参,无返回值方法
// Method method=c1.getMethod("show", null);
// Object zhangsan=c1.newInstance();
Object lisi=c1.getConstructor(String.class,int.class,String.class).newInstance("李四",20,"男");
// method.invoke(lisi, null);
//4获取公开无参,带返回值得方法
// Method method2=c1.getMethod("getInfo", null);
// String info= (String) method2.invoke(lisi, null);
// System.out.println(info);
//5获取公开带参,无返回值
// Method method3=c1.getMethod("show", String.class);
// method3.invoke(lisi, "北京");
//6调用静态方法
// Method method4=c1.getMethod("showConntry", null);
// method4.invoke(null, null);
//7调用私有方法
Method method5=c1.getDeclaredMethod("show", String.class,String.class);
method5.setAccessible(true);
method5.invoke(lisi, "上海","1608");
//8获取类中私有属性
Field field=c1.getDeclaredField("name");
field.setAccessible(true);
//赋值
field.set(lisi, "李思思");
//获取
String s=(String) field.get(lisi);
System.out.println(s);
// Field field2=c1.getDeclaredField("country");
// field2.set(null, "美国");
// String s2=(String) field2.get(null);
// System.out.println(s2);
}
}
package com.qf.day30_2;
/**
* 人类
* @author wgy
*
*/
public class Person {
private String name;
private int age;
private String gender;
public static String country="中国";
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age, String gender) {
super();
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;
}
/**
* 显示信息
*
*/
public void show(){
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender);
}
/**
* 显示信息 带参数
* @param address
*/
public void show(String address){
System.out.println("姓名:"+name+" 年龄:"+age+" 性别:"+gender+" 地址:"+address);
}
/**
* 返回信息
* @return
*/
public String getInfo(){
return "姓名:"+name+" 年龄:"+age+" 性别:"+gender;
}
public static void showConntry(){
System.out.println("这是一个静态方法,国家是:"+country);
}
private void show(String address,String grade){
System.out.println("这是一个私有方法,地址:"+address+" 年级:"+grade);
}
}
案例二
public class Dog_Reflect_Main01 {
public static void main(String[] args) throws ClassNotFoundException {
//创建Class类对象
Class<Dog> class1=(Class<Dog>) Class.forName("com.qianfeng.demo1.Dog");
//getDeclaredFields:获取对应类中所有的字段(不包含继承来的)
Field[] arrDF=class1.getDeclaredFields();
System.out.println("getDeclaredFields:");
//增强for循环遍历输出数组内容
for(Field f:arrDF)
{
//getName:获取属性名称
System.out.println(f.getName());
}
//getFields:获取对应类中所有公共字段(包含继承来的)
Field[] arrF=class1.getFields();
System.out.println("getFields:");
//增强for循环遍历输出数组内容
for(Field f:arrF)
{
System.out.println(f);
}
//getDeclaredMethods:获取对应类中的所有方法(不包含继承来的)
Method[] arrDM=class1.getDeclaredMethods();
System.out.println("getDeclaredMethods:");
//遍历输出
for(Method m:arrDM)
{
System.out.println(m);
}
//getMethods:获取对应类中的所有公共方法(包含继承来的):public
Method[] arrM=class1.getMethods();
System.out.println("getMethods:获取方法");
//遍历输出
for(Method m:arrM)
{
System.out.println(m);
}
}
}
常用方法
1、getDeclaredFields:获取对应类中所有的字段(不包含继承来的)
2、getFields:获取对应类中所有公共字段(包含继承来的)
3、getDeclaredMethods:获取对应类中的所有方法(不包含继承来的)
4、getMethods:获取对应类中的所有公共方法(包含继承来的):public
5、forName:根据指定的类名获取对应的Class对象
6、newInstance():创建对象类的对象
7、getDeclaredField():获取对应类中的方法对象
2、getFields:获取对应类中所有公共字段(包含继承来的)
3、getDeclaredMethods:获取对应类中的所有方法(不包含继承来的)
4、getMethods:获取对应类中的所有公共方法(包含继承来的):public
5、forName:根据指定的类名获取对应的Class对象
6、newInstance():创建对象类的对象
7、getDeclaredField():获取对应类中的方法对象
反射技术的优缺点
优点:
1 提高了Java程序的灵活性和扩展性,降低了耦合性,提高自适应能力
2 允许程序创建和控制任何类的对象,无需提前硬编码目标类
2 允许程序创建和控制任何类的对象,无需提前硬编码目标类
缺点:
性能问题
代码维护问题
代码维护问题
反射的应用领域
如软件测试、 EJB、JavaBean等开源框架例如Struts、Hibernate、Spring