您的位置:首页 > 编程语言 > Java开发

java 反射机制的基本知识

2016-07-22 20:24 543 查看
一下均是来自己看自李兴华老师的视频笔记,他讲的视频挺好的,自己写的估计只能自己看的懂,想更加清楚的了解,请观看他的视频。

前天看那个java学习路线的一张图上看了看,里面有一节内容讲的是反射,我就搜集资料视频学了学。

我们平常访问普通的方法都是在哪里进行使用new进行创建对象,再利用创建的对象进行访问这个方法。

那么我们如何在不使用new关键字的情况下进行访问这些对象和属性呢?new关键字是造成耦合度高的重要原因

Java 的反射就是在程序动态的运行中进行访问方法和属性;

一般来说创建并实例化一个程序一般有三种方法:通过new关键字  --   通过 clon -- 另一种就是反射,今天说说反射。

先看一下怎么利用反射进行创建对象和实例化。

一、利用反射进行创建对象和实例化。

Person类就不贴了,就是有两个属相private String name ,private int age,属性设置get set toString 方法

package com.hejingzhou.tcoy;

public class Test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

Person person = new Person();
Class cla_1 = person.getClass();
Object obj_1 = cla_1.newInstance();
System.out.println(obj_1);
System.out.println("###############################");

Class cla_2 = Person.class;
Object obj_2 = cla_2.newInstance();
System.out.println(obj_2);
System.out.println("###############################");

Class cls_3 = Class.forName("com.hejingzhou.tcoy.Person");
System.out.println(cls_3);//获的是 完整的类
Object obj_3 = cls_3.newInstance();
//Person person = (Person)obj_3;
//System.out.println(person.getAge());
System.out.println(obj_3);
}
}

二、反射创建对象实例的应用

interface IFruit{
void eat();
}

class Apple implements IFruit{

public void eat() {
// TODO Auto-generated method stub
System.out.println("吃苹果");
}

}
class Orange implements IFruit{

public void eat() {
// TODO Auto-generated method stub
System.out.println("吃橘子");
}

}

class Factoty{
public static IFruit getInstance(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
//使用反射前的工厂模式,每次添加新的水果就得需要进行修改工厂模式类中的if语句
//		if(className.equals("Apple")){
//			return new Apple();
//		}
/***
* 使用后只需要填入类的详细类名就可以
*/
IFruit fruit = null;
fruit = (IFruit) Class.forName(className).newInstance();
return fruit;
}
}

public class Test {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
//<span style="white-space:pre">		</span>Factoty.getInstance("Apple");//使用反射机制之前的工厂模式
IFruit fApple = Factoty.getInstance("com.hejingzhou.q.Orange");
fApple.eat();
}
}


这样做出的应用更适用于更改信息,非开发人员更容易进行操作。

三、利用反射进行设置一个基本的属性

看一下这里的Book 类
package com.hejingzhou.r;

class Book {
private  String title;

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String toString() {
return "Book [title=" + title + "]";
}

}
Test一下
package com.hejingzhou.r;

import java.lang.reflect.Field;

public class Test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException {
Class cls = Class.forName("com.hejingzhou.r.Book");
Object obj = cls.newInstance();
Field titleField = cls.getDeclaredField("title");
titleField.setAccessible(true);//取消程序入口检查  否则title是private修饰的,是无法访问的
titleField.set(obj,"Java开发");
System.out.println(titleField.get(obj));
}

}

打印结果:Java开发
Field类就是一个动态访问类或接口的字段的入口。
public Field getDeclaredField(String name)
throws NoSuchFieldException,
SecurityException
Returns a Field object that reflects the specified declared field of the class or interface represented by this Class object. The name parameter is a String that specifies the simple name of the desired field.

public void setAccessible(boolean flag)
throws SecurityException
Set the accessible flag for this object to the indicated boolean value. A value of true indicates that the reflected object should suppress Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks
set(Object obj, Object value)
Sets the field represented by this Field object on the specified object argument to the specified new value.
这样就可以动态的设置字段参数。

四、动态的设置构造方法

Book类必须有一个空参构造
package com.hejingzhou.w;

public class Book {
private String title;
private double price;

public Book(){
}

public Book(String title){
this.title = title;
System.out.println("我是只有一个参数的构造方法");
}

public Book(String title, double price) {
super();
this.title = title;
this.price = price;
}
public String toString() {
return "Book [title=" + title + ", price=" + price + "]";
}

}
详细的管理构造参数一下
package com.hejingzhou.w;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
Class cls = Class.forName("com.hejingzhou.w.Book");
//		Object apogee = cls.newInstance();//这样实例化  就只能调用 类中默认的无参构造方法
//		System.out.println(obj);

Constructor constructor = cls.getConstructor(new Class[]{String.class,double.class});
Object object = constructor.newInstance(new Object[]{new String("Java开发"),new Double(43.9)});//"Java开发",43.2
System.out.println(object);

Constructor constructor2 = cls.getConstructor(new Class[]{String.class});
Object object2 = constructor2.newInstance(new Object[]{new String("Android开发")});
System.out.println(object2);

}
}
这是java1.8环境下在进行构造方法赋值 的时候进行需要创建一个Object类型数组进行添加对应的数据,但是在视频中,是直接进行赋值的,这点需要注意,

五、操作get set 方法

Frult类(操作类)
package com.hejingzhou.e;

public class Fruit {

private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String toString() {
return "Fruit [name=" + name + "]";
}

}
进行设置操作get set方法的操作
package com.hejingzhou.e;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException, NoSuchMethodException,
SecurityException, IllegalArgumentException, InvocationTargetException {
String fieldName = "name";
Class cla = Class.forName("com.hejingzhou.e.Fruit");
Object obj = cla.newInstance();
//System.out.println(obj);
Method setMet = cla.getMethod("set"+initCap(fieldName), new Class[]{String.class});
Method getMet = cla.getMethod("get"+initCap(fieldName), null);
setMet.invoke(obj,new Object[]{new String("java 开发")} );
System.out.println(getMet.invoke(obj, null));
}
//返回字符串首字母大写
public static String initCap(String str){
return str.substring(0,1).toUpperCase()+str.substring(1);
}
}

打印结果
Book [title=Java开发, price=43.9]

我是只有一个参数的构造方法

Book [title=Android开发, price=0.0]

这样就可以进行控制方法了。
这就是反射的基本应用,一般都应用与框架中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java反射