可变参数和反射

可变参数和反射

第一章 可变参数

从java的JDK 1.5开始,Java允许为方法定义长度可变的参数

语法:

public void foo(int ... args){
    //int ... 表示数组
}

注意:

调用可变参数的方法时, 编译器将自动创建一个数组保存传递给方法的可变参数,因此,程序员可以在方法体中以数组的形式访问可变参数.

可变参数只能处于参数列表的最后, 所以一个方法最多只能有一个长度可变的参数.

示例:

public static void main(String[] args) { 
    int[] nums={10,20,30}; 
    showNumber(nums); 
    //----可变参数调用 好处:调用是可以传递数组元素 
    //注意:1 可以必须放在方法参数列表的最后 
    // 2 一个只能有一个可变参数 
    showNumber(10,20); 
    //showNames("zhangsan","lisi","wangwu"); 
}
public static void showNumber(int... nums){ 
    // ... []
    System.out.println(nums.length);
    for (int i : nums) { 
        System.out.println(i); 
    } 
}
public static void showNames(String...names){
    for (String n : names) {
        System.out.println(n);
    }
}

第二章 反射

1. 为什么使用反射

需求:

我公司定义了一组接口,然后第三方公司按照我公司的接口实现了一套功能,然后交给我们,但是我们公司的项目已经结束,如何实现动态加载第三方公司提供的功能。

2.什么是反射

反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。

3.反射常用的类
  • Class类—可获取类和类的成员信息
  • Field类—可访问类的属性
  • Method类—可调用类的方法
  • Constructor类—可调用类的构造方法

第三章 Class类

1.Class类是反射机制的起源和入口
  • 每个类都有自己的Class对象
  • 用于获取与类相关的各种信息
  • 提供了获取类信息的相关方法
  • Class类继承自Object类
2.Class类存放类的结构信息
  • 类名
  • 父类﹑接口
  • 方法﹑构造方法﹑属性
  • 注释
3.获取Class对象的3中方式
//方法1:对象.getClass() 通过对象获取
Student stu=new Student(); 
Class clazz=stu.getClass();
//方法2:类.class  通过类过去
clazz= Student.class; 
clazz=String.class;
//方法3:Class.forName()  通过全路径获取
clazz=Class.forName("java.lang.String"); 
clazz=Class.forName("java.util.Date");
4.获取类的其他结构信息
Class clazz = Class.forName("java.lang.Object");
//获取Field 对象 属性
Field fields[ ] = clazz.getDeclaredFields();
//获取Method 对象  方法
Method methods[] = clazz.getDeclaredMethods();
//获取Constructor对象 构造器
Constructor constructors[ ] = clazz.getDeclaredConstructors();
5.动态创建对象
  1. 方法一,使用Class的newInstance()方法,仅适用无参构造方法

    Class clazz=Class.forName("com.qf.reflection.Student"); 
    Object obj=clazz.newInstance();
    
  2. 方法二,使用Constructor的newInstance()方法,适用所有的构造器

    Constructor cons = clazz.getConstructor(new Class[]{ 
        String.class, int.class, float.class }); 
    Object obj = cons.newInstance(new Object[ ] {"lkl", 32, 56.5f });
    
6.动态执行方法
  1. 通过Class获取对象

  2. 调用Method对象的invoke()方法

    Object invoke(Object obj,Object [] args); 
    //object 返回值 
    //obj 当前方法所属对象 
    //args 当前方法的参数列表
    
    
    package net.xsoftlab.baike;
    import java.lang.reflect.Method;
    public class Person {
    	public static void main(String[] args) throws Exception {		
    		Class<?> clazz = Class.forName("net.xsoftlab.baike.Person");
    		// 调用Person类中的run方法
    		Method method = clazz.getMethod("run");
    		method.invoke(clazz.newInstance());
    		// Java 反射机制 - 调用某个类的方法1.
    		// 调用Person的Speak方法
    		method = clazz.getMethod("Speak", int.class, String.class);
              method.invoke(clazz.newInstance(), 22, "小明");
            // Java 反射机制 - 调用某个类的方法2.
            // age -> 22. name -> 小明
    	}
    	public void run(){
    		System.out.println("调用Person类的run方法");
    	}
    	public void Speak(int age, String name){
    		System.out.println("调用Person类的Speak方法");
    		System.out.println("age -> " + age + ". name -> " + name);
    	}
     
    }
    
7.反射动态的操作属性
	1. 通过Class对象获取Field对象
	2. 调用Field对象的方法进行取值或者赋值操作
方法 说明
Xxx getXxx(Object obj) 获取基本类型的属性值
Object get(Object obj) ) 得到引用类型属性值
void setXxx(Object obj,Xxx val) 将obj对象的该属性设置成val值
void set(Object obj,object val) 将obj对象的该属性设置成val值
void setAccessible(bool flag) 对获取到的属性设置访问权限
8.反射技术的优点和缺点

优点:

1.提高了Java程序的灵活性和扩展性,降低了耦合性,提高自适应能力

2.允许程序创建和控制任何类的对象,无需提前硬编码目标类

缺点:

1.性能问题

2.代码维护问题

类对象常用方法
		//获取 类对象   ==》 Student.class   文件
		Class c = Student.class;
		//1.getName()  获取的是类对象的名字
		System.out.println(c.getName());//com.qf.reflect.method.Student
		//2.getPackage() 获取包名
		System.out.println(c.getPackage().getName());
		//3. getSuperClass  获取父类
		System.out.println(c.getSuperclass());
		//4.getInterfaces 获取所有的接口
		Class[] interfaces = c.getInterfaces();
		for (Class interface1 : interfaces) {
			System.out.println(interface1);
		}
		System.out.println("------------------------------");
		
		//5.getFileds 获取的是本类以及父类所有的公共属性
		Field[] fields = c.getFields();
		for (Field field : fields) {
			System.out.println(field.getName());
		}
		System.out.println("-----------");
		//6. getdeclaredFields() 获取本类中所有声明的属性包括私有属性
		Field[] declaredFields = c.getDeclaredFields();
		for (Field field : declaredFields) {
			System.out.println(field.getName());
		}
		System.out.println("-----------");
		//7.getMethods()  获取 所有本类以及父类公共方法
		Method[] methods = c.getMethods();
		for (Method method : methods) {
			System.out.println(method.getName());
		}
		System.out.println("-----------");
		//8.getDeclaredMethods() 获取本类中所有声明了的方法(包括私有)
		Method[] declaredMethods = c.getDeclaredMethods();
		for (Method method : declaredMethods) {
			System.out.println(method.getName());
		}
		System.out.println("-----------");
		//9.getConstructors()获取所有构造器
		Constructor[] constructors = c.getConstructors();
		for (Constructor constructor : constructors) {
			System.out.println(constructor.getName());
		}
		//10.newInstance()  通过类对象 创建 类的对象
		Object obj = c.newInstance();
		Student stu = (Student)obj;
		stu.show(10);//就是一个Student对象

class Person{
	public double height;
	
}
class Student extends Person implements Runnable,Serializable{
	
	public int age;
	public String sex;
	public String name;
	String hobby;
	private double weight;

	public Student(int age, String sex, String name) {
		super();
		this.age = age;
		this.sex = sex;
		this.name = name;
	}
	
	public Student() {
		super();
	}

	public void show(){}
	public void show(int age){System.out.println("我今年:"+age);}
	public void play(){}
	void introduce(){}
	private void display(){}

	@Override
	public String toString() {
		return "Student [age=" + age + ", sex=" + sex + ", name=" + name + "]";
	}
	@Override
	public void run() {	
	}
}
通过反射给属性赋值
//1. 通过类对象 获取具体的属性
//2. set(具体给哪个实例对象赋值,值)

如何给私有属性赋值
    getDeclaredField(属性名)
    打开权限  setAccessible(true)
    再赋值  set()
    //获取类对象
		Student stu1 = new Student();
		Student stu2 = new Student();
		Student stu3 = new Student();
		
		Class c = stu1.getClass();
		
	    //获取属性
		Field field = c.getField("age");  //Filed  
		//set(具体哪个实例对象,值)
		field.set(stu1, 18);
		
		Field field2 = c.getField("age"); 
		field2.set(stu2, 20);
		
		Field field3 = c.getField("name");
		
		field3.set(stu1, "周杰伦");
		field3.set(stu2,"蔡依林");
		
		Field field4 = c.getField("sex");
		field4.set(stu1,"男");
		field4.set(stu2,"女");
	
		Field df = c.getDeclaredField("weight");
		//此时需要打开权限,因为weight属性在Student中定义为private私有
		df.setAccessible(true);
		df.set(stu1, 70);
		df.set(stu2, 50);
		
		System.out.println(stu1);
		System.out.println(stu2);

总结

1 简述反射机制

反射是一种间接操作目标对象的机制,在程序程序运行时获取或者设置对象自身的信息。
只要给定类的名字,就可以通过反射获取类的所有信息,接着便能调用它的任何一个方法和属性。

反射的步骤有哪些?

第一:获取类加载器:
ClassLoader loader=Thread.currentThread().getContextClassLoader();
//获取当前线程的上下文类加载器

第二:通过类加载器获取类
Class clazz=loader.loadClass(“com.taobao.reflect.car”)
//通过对象的全称限定来获取对象。

第三:通过clazz获得构造函数:
Constructors cons=clazz.getDeclaraedConstructors(Class[]null);
//调用默认的构造函数

第四:然后通过构造函数构造对象:
Car car=(Car)cons.newInstance();
//获取类的默认构造函数对象并实例化对象。

第五:得到car对象,然后调用car的方法:
Method methd =car.getMethod(“setName”,“String.class”);
//method声明,并指向car的setName这个方法,得到setName方 法。

2 用反射机制能干什么事
刚开始在使用jdbc时侯,在编写访问数据库时写到想吐,有八个表,每个表都有增删改查中操作,那时候还不知道有反射 机制这个概念,所以就对不同的表创建不同的dao类,这样不仅开发速率慢,而且代码冗余的厉害,最要命的是看着差不多 的,然后直接复制修改,由于容易犯各种低级的错误(大小写啊,多一个或少一个字母啊……),一个错误就可以让你找半天。 有了java反射机制,什么都好办了,只需要写一个dao类,四个方法,增删改查,传入不同的对象,就OK啦,无需为每一个 表都创建dao类,反射机制会自动帮我们完成剩下的事情,这就是它的好处。说白了,反射机制就是专门帮我们做那些重复的 有规则的事情,所以现在很多的自动生成代码的软件就是运用反射机制来完成的,只要你按照规则输入相关的参数,所以低 级的程序员慢慢的就被抹杀了,为什么?因为代码都不用写了,随便一个人都会开发,还要程序员干什么啊?所以我们只有 一条出路,那就是努力努力再努力,成为高级程序员,专门开发傻瓜软件,让其他程序员 到一边凉快去~

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读