ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java - 基础 - 反射

2021-09-21 09:32:04  阅读:160  来源: 互联网

标签:反射 Java String title 基础 public Book Class cls


Java - 基础 - 反射

反射机制

  1. 什么是反射

  2. 反射的作用

  3. 利用反射调用类结构

1.认识反射

正:正常情况下,先有类,之后才会有类的对象

反:可以利用对象找到对象的出处

​ 取得Classs对象:

public final Class<?> getClass()

该方法继承自Object类,所以,所有的类都有这个方法

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

2.Class类对象实例化

java.lang.Class是一个类。该类是反射的源头,该类有三种实例化方法,如下:

  • 调用Object类中的getClass()方法

    public static void main(String[] args) {
    	Date date = new Date();
    	Class <?> cls = date.getClass();
    	System.out.println(cls);
    }
    
  • 使用"类.class"取得

    public static void main(String[] args) {
    	Class <?> cls = Date.Class;
    	System.out.println(cls);
    }
    
  • 调用Class类提供的方法

    实例化Class对象:

    public static Class<?> forName(String className)
    throws ClassNotFoundException

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

    此时可以不使用import进行导入

3.反射实例化对象

当拿到一个类的时候,使用new 实例化对象。如果存在Class类对象,就可以通过反射进行对象的实例化

实例化对象方法:

public T newInstance() throws InstantiationException, IllegalAccessException

示例

class Book{
	
	public Book() {
		System.out.println("********************");
	}
	public String toString() {
		return "这是一本书";
		
	}
}
public class test {
	public static void main(String[] args) throws Exception {
        //1.常规方法,new对象
		Book b = new Book();
		System.out.println(b);
		
        //2.反射对象
		Class<?> cls = Class.forName("com.String.Book");
		Object o = cls.newInstance();
        Book book = (Book)o;
		System.out.println(o);//输出b和o结果一样
	}
}

4.反射调用构造

当类中只有有参构造的时候,通过反射调用,会产生异常

错误代码示例

package com.String;

public class test {
	public static void main(String[] args) throws Exception {

		Class<?> cls = Class.forName("com.t.Book");
		Object o = cls.newInstance();
		System.out.println(o);
	}
}

Book类,位于其他包

package com.t;

public class Book{
	private String title;
	private double price;
	
	public Book(String title , double price) {
		this.title = title ;
		this.price = price;
	}
	public String toString() {
		return "书名:"+this.title+",价格:"+this.price;
		
	}
}

异常信息

Exception in thread "main" java.lang.InstantiationException: com.t.Book
	at java.lang.Class.newInstance(Unknown Source)
	at com.String.test.main(test.java:11)
Caused by: java.lang.NoSuchMethodException: com.t.Book.<init>()
	at java.lang.Class.getConstructor0(Unknown Source)
	... 2 more

解决方法:

在Class类中,提供有获取构造方法的方法

  • 取得全部构造方法:

    public Constructor <?> [] getConstructors()

  • 取得一个指定参数的构造方法:

    public Constructor < T > getConstructor(Class<?>… parameterTypes)

上面两个方法的返回值**Constructor **是java.lang.reflect.Constructor类的对象,在这个类中提供有一个明确传递有参构造内容的实例化对象方法

public T newInstance(Object... initargs)

解决代码示例:

package com.String;

import java.lang.reflect.Constructor;

public class test {
	public static void main(String[] args) throws Exception {

		Class<?> cls = Class.forName("com.t.Book");
		Constructor<?> con = cls.getConstructor(String.class,double.class);
		Object o = con.newInstance("java开发",79.8);
		System.out.println(o);
	}
}

简单JAVA类的开发之中,至少保留一个无参构造,反射调用不方便

5 .反射调用方法

类中的普通方法,只有在类产生实例化对象之后才可以调用。

实例化对象的方式有三种

  1. new一个对象
  2. 克隆一个对象
  3. 反射一个对象

在Class类中,提供有取得方法的操作

  • 取得一个类中的全部方法

    public Method[] getMethods()
    
  • 取得指定名称的方法

    public Method getMethod(String name, Class<?>... parameterTypes)
    

    name是方法名称

上面两个方法的返回值**Method **是java.lang.reflect.Method 类的对象

  • 调用方法:

    public Object invoke(Object obj,
                         Object... args)
    

示例代码

Book类,位于其他包

package com.t;

public class Book{
	private String title;

	public String getTitle() {
		return title;
	}

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

调用方法:

package com.String;
import java.lang.reflect.Method;

public class test {
	public static void main(String[] args) throws Exception {
		String fielName = "title";
		Class<?> cls = Class.forName("com.t.Book");
		Object o = cls.newInstance();
		Method setMet = cls.getMethod("set" +initcap(fielName), String.class);
		Method getMet = cls.getMethod("get" +initcap(fielName));	
		setMet.invoke(o, "java开发");
		System.out.println(getMet.invoke(o));	
	}
	
	//首字母大写
	public static String initcap(String str) {
		return str.substring(0, 1).toUpperCase()+str.substring(1);
	}
}

6.反射调用成员

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

  • 取得全部成员

    public Field[] getDeclaredFields()
    
  • 取得指定成员

    public Field getDeclaredField(String name)
    

上面两个方法的返回值Field是java.lang.reflect.Field类的对象,该类提供有如下常用方法

  • 取得属性内容

    public Object get(Object obj)
    
  • 设置属性内容

    public void set(Object obj,Object value)
    

使用示例:

Book类,位于其他包

package com.t;

public class Book{
	private String title;

	public String getTitle() {
		return title;
	}

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

反射调用:

package com.String;

import java.lang.reflect.Field;

public class test {
	public static void main(String[] args) throws Exception {
		//1.实例化类对象
		Class<?> cls = Class.forName("com.t.Book");
		Object o = cls.newInstance();
		//取得成员
		Field titleField = cls.getDeclaredField("title");
		//取消封装,不取消无法访问private变量
		titleField.setAccessible(true);
		//设置成员变量
		titleField.set(o, "python");
		System.out.println(titleField.get(o));	
	}
}

构造方法和普通方法也可以取消封装

7.总结

  1. 实例化对象的方式多了一种:反射
  2. 简单JAVA类需要使用无参构造以及使用set\get方法的原因

标签:反射,Java,String,title,基础,public,Book,Class,cls
来源: https://blog.csdn.net/weixin_43308622/article/details/120398676

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有