反射机制
        1.观察 Class 类的使用
        2.利用反射改善工程设计模式
        3.反射操作类结构
        
    content (内容)
        1.认识反射
            既然是反,那么就有正。正常的思路中只有知道一个类之后才可以产生实例化对象
            
            范例:正常的操作

package cn.mysterious.study3;

import java.util.Date;

public class ReflexMechanism {

    public static void main(String[] args) {
// TODO Auto-generated method stub
java.util.Date data = new Date();
System.out.println(data);
} }

所谓的反指的就是通过对象找到来源,那么在程序中,对象要想找到它的来源就必须依靠 Object 类提供的一个方法完成:
                public final Class<?> getClass()
                
            范例:观察反

package cn.mysterious.study3;

import java.util.Date;

public class ReflexMechanism {

    public static void main(String[] args) {
// TODO Auto-generated method stub
java.util.Date data = new Date();
System.out.println(data.getClass());
} }

现在发现通过 getClass() 取得的 Class 类对象,就可以直接找到该对象的来源
            
        2.实例化 Class 类
            Class 类是反射操作的源头,也就是说所有的反射操作都应该通过Class 完成,但是最有意思的是这个类的对象可以通过三种实例化
                第一种:利用 Object 类中的 getClass() 方法 ,必须有明确的实例化对象后可以调用

package cn.mysterious.study3;

import java.util.Date;

public class ReflexMechanism {

    public static void main(String[] args) {
// TODO Auto-generated method stub
java.util.Date data = new Date();
Class<?> cls = data.getClass();
System.out.println("全名:" + cls.getName());
System.out.println("类名:" + cls.getSimpleName());
} }

第二种:利用“ 类.class ”取得 Class 类的实例化对象,等到学习到 Hibernate , MyBatis 的时候会使用到此模式

package cn.mysterious.study3;

import java.util.Date;

public class ReflexMechanism {

    public static void main(String[] args) {
// TODO Auto-generated method stub
Class<?> cls = Date.class;
System.out.println("全名:" + cls.getName());
System.out.println("类名:" + cls.getSimpleName());
} }

(这个不知道怎么说 一个是有 import 调用好包 一个是出错?)

package cn.mysterious.study3;

public class ReflexMechanism {

    public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Class<?> cls = java.util.Date.class;
System.out.println("全名:" + cls.getName());
System.out.println("类名:" + cls.getSimpleName());
} }

第三种:利用 Class 类的 static 方法取得
                    实例化 Class 对象: public static Class<?> forName(String className)throws ClassNotFoundException

package cn.mysterious.study3;

public class ReflexMechanism {

    public static void main(String[] args)throws Exception {
// TODO Auto-generated method stub
Class<?> cls = Class.forName("java.util.Date"); // 字符串
System.out.println("全名:" + cls.getName());
System.out.println("类名:" + cls.getSimpleName());
} }

现在最为重要的模式就是使用 Class.forName() 方法,它的好处是可以直接写字符串

        3.通过反射实例化对象(核心)
            如果要产生实例化对象,本质上来讲必须有关键字 new才可以实现,但是这一切在有了反射之后变了
            在 Class 类中提供有如下一个方法:public T newInstance()throws InstantiationException,IllegalAccessException
            
            范例:正常实例化对象

package cn.mysterious.study3;

import java.util.Date;

public class ReflexMechanism {

    public static void main(String[] args) {
// TODO Auto-generated method stub
Date data = new Date();
System.out.println(data);
} }

范例:反射实例化对象

package cn.mysterious.study3;

import java.util.Date;

public class ReflexMechanism {

    public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("java.util.Date"); // 字符串
Date data = (Date) cls.newInstance();// 实例化对象:new Date()
System.out.println(data);
} }

下面再观察一个自定义的类i对象实例化
            
            范例:自定义实例化对象

package cn.mysterious.study3;

class Person{
public Person(){
System.out.println("*** 新的 Person类对象实例化 ***");
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "人";
}
} public class ReflexMechanism { public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.mysterious.study3.Person"); // 字符串
Person p = (Person) cls.newInstance();// 实例化对象:new Date()
System.out.println(p);
} }

反射实例化对象最终也要调用无参构造方法进行实例化操作
            
        4.工厂设计模式的修正(理解)
            工厂设计模式的本质就在于要想取得接口的实例化对象不要直接使用关键字 new ,而应该通过工厂取得
            (总结:只要是自己写的接口要想取得实例化对象,99%要写工厂类)
            
            范例:传统工厂设计

package cn.mysterious.study3;

interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃");
}
}
class Factory{
public static Fruit getInstance(String classNaame) {
if ("apple".equalsIgnoreCase(classNaame)) {
return new Apple();
}
return null;
}
} public class ReflexMechanism { public static void main(String[] args) throws Exception {
Fruit f = Factory.getInstance("apple");
f.eat();
} }

但是现在对于工厂设计模式却出现了一个挑战,如果喜爱女子增加了子类,那么意味着工厂类需要修改
            那么假如这个接口可能源源不断的生产新的子类。所以这个时候的工厂类设计就存在有新的问题了
            那么现在的关键性问题就在于new上了,new是照成本次设计失败的最大元凶。所以这个时候就可以通过反射来实现此时的工厂类

package cn.mysterious.study3;

interface Fruit{
public void eat();
}
class Apple implements Fruit{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃苹果");
}
}
class Orange implements Fruit{
@Override
public void eat() {
// TODO Auto-generated method stub
System.out.println("吃橙子");
}
}
class Factory{
public static Fruit getInstance(String classNaame) {
try {
return (Fruit) Class.forName(classNaame).newInstance();
} catch (Exception e) {
// TODO: handle exception
return null;
}
}
} public class ReflexMechanism { public static void main(String[] args) throws Exception {
Fruit f = Factory.getInstance("cn.mysterious.study3.Orange");
f.eat();
} }

以上的代码只是分析出了关键字 new 实例化对象与构造方法实例化对象的区别,但是并不意味着不使用 关键字 new

        5.调用构造方法
             利用 Class 类中的 newInstance 方法其主要的目的是可以取得类的实例化对象,但是这种取得的操作本身是存在有问题的。因为它只能调用类中的去参构造。
             如果类中没有提供无参构造方法,那么就必须明确的调用指定的构造方法实现对象的实例化操作
             要想实现这样的操作,那么必须要找到类中的构造方法定义:
                public Constructor<T> getConstructor(Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException
            
            找到了 java.lang.reflect.Constructor 类之中在此类中提供有一个实例化对象的方法:
                实例化对象:
                    public T newInstance(Object... initargs)
                        throws InstantiationException,
                            IllegalAccessException,
                            IllegalArgumentException,
                            InvocationTargetException
                            
            范例:调用指定构造实例化对象

package cn.mysterious.study3;

import java.lang.reflect.Constructor;

class Person {
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "姓名:" + this.name + ",年龄:" + this.age + "\n";
}
} public class ReflexMechanism { public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.mysterious.study3.Person");
Constructor<?> cons = cls.getConstructor(String.class,int.class);
Person per = (Person) cls.newInstance();// 实例化对象:new Date()
System.out.println(per);
} }

还是类中提供无参构造省事
            
        6.调用方法
            类中的普通方法是在取得本类的实例化对象之后才可以进行调用的操作。所以即便使用了反射进行方法的调用
            那么也必须使用 newInstance() 取得实例化对象,在 Class 类中定义有如下取得方法对象的操作
                取得方法:
                    public Method getMethod(String name,Class<?>... parameterTypes)
                                throws NoSuchMethodException,SecurityException
            getMethod() 方法返回的是 java.lang.reflect.Method 类对象,在这个类中有一个最为重要的方法:
                调用方法:

public Object invoke(Object obj,Object... args)
throws IllegalAccessException,IllegalArgumentException,InvocationTargetException package cn.mysterious.study3; import java.lang.reflect.Constructor;
import java.lang.reflect.Method; class Person {
private String name;
public Person(String name){
this.name = name;
}
public String getName() {
return name;
}
} public class ReflexMechanism { public static void main(String[] args) throws Exception {
String attribute = "name"; // 要求? value = "少爷"
Class<?> cls = Class.forName("cn.mysterious.study3.Person");
Object obj = cls.newInstance(); // 实例化对象
Method setMrthod = cls.getMethod("set" + initcap(attribute), String.class);
Method getMrthod = cls.getMethod("get" + initcap(attribute));
setMrthod.invoke(obj, "少爷"); // 等价于: 对象。setName("少爷")
System.out.println(getMrthod.invoke(obj));
}
public static String initcap(String str){
return str.substring(0,1).toLowerCase() + str.substring(1);
}
}

以后程序中如果给了属性名称,类的完整名称,而后可以进行自动的赋值操作,那么基本上就是反射机制在里面起作用

        7.调用成员
            在类中的成员需要考虑两种因素(Class 类定义的方法)
                父类继承而来的成员: public Field getField(String name)throws NoSuchFieldException,SecurityException
                本类定义的成员: public Field getDeclaredField(String name)throws NoSuchFieldException,SecurityException
            在java中使用 java.lang.reflect.Field 类描述成员,在这个类中有两个方法:
                取得成员内容: public Object get(Object obj)throws IllegalArgumentException,IllegalAccessException
                设置成员内容: public void set(Object obj,Object value)throws IllegalArgumentException,IllegalAccessException
            但是需要注意的是所有属性几乎都要使用 private 封装,所以要想解决封装的困扰
            可以利用 Field 父类的方法完成( java.lang.reflect.AccessibleObject ):
                取消封装: public void setAccessible(boolean flag)throws SecurityException
            
            范例:直接进行属性调用

package cn.mysterious.study3;

import java.lang.reflect.Field;

import javax.naming.NameNotFoundException;

class Person { // (想法:可不可以继承,继承 person)
private String name; } public class ReflexMechanism { public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("cn.mysterious.study3.Person");
Object obj = cls.newInstance(); // 实例化对象
Field nameField = cls.getDeclaredFields();
nameField.setAccessible(true); // private 消失了
nameField.set(obj,"少公子"); // 对象。name = “少公子”;
System.out.println(nameField.get(obj));
}
}

几乎类中的一切定义形式都可以通过反射完成
        
    总结
        在基础学习阶段对于反射有个认识就行了,暂时不需要编写代码
        Class Constructor Method Field 类的作用应该有个印象
        反射与工厂设计模式结合的产物

菜鸡的Java笔记 - java 反射机制的更多相关文章

  1. 浅说Java中的反射机制(二)

    写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...

  2. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  3. 黑马程序员——【Java高新技术】——反射机制

    ---------- android培训.java培训.期待与您交流! ---------- 一.概述 1.Java反射机制:是指“在运行状态中”,对于任意一个类,都能够知道这个类中的所有属性和方法: ...

  4. Java 中的反射机制

    JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法:这种动态获取的信息以及动态调用对象的方法的功能称为ja ...

  5. JAVA类型信息——反射机制

    JAVA类型信息——反射机制 一.反射机制概述 1.反射机制:就是java语言在运行时拥有的一项自我观察的能力,java通过这种能力彻底了解程序自身的情况,并为下一步的动作做准备. 2.反射机制的功能 ...

  6. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  7. java学习之反射机制

    java语言区别于C,C++等准静态语言的最大特点就是java的反射机制.静态语言的最直接定义就是不能在运行时改变程序结构或变量的类型.按照这样的定义,python,ruby是动态语言,C,C++,J ...

  8. java基础之反射机制

    一.概念 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...

  9. 深入理解Java中的反射机制

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制. ...

  10. 谈一谈java里面的反射机制

    首先来看看百度百科中是如何定义的: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方 ...

随机推荐

  1. Java-对象克隆

    1. 为什么要克隆 在java中,我们通过直接=等号赋值的方法来拷贝,如果是基本数据类型是没有问题的,例如 int i = 1; int j = 0; j = i; // 直接=等号赋值,这样是没有问 ...

  2. c++ class里面成员和分配内存问题

    慢慢开始学c++啦,记录学习的大体过程 class中神奇的内存(sizeof) 1.内存补齐 便于管理类(生成的对象)的内存,类总内存总是为最大成员字节大小的倍数,不足的会进行内存补齐 类的整体内存就 ...

  3. 阿里:MySQL数据库规范

    阿里:MySQL数据库规范 简介:基于阿里数据库设计规范扩展而来 设计规范 1.[推荐]字段允许适当冗余,以提高查询性能,但必须考虑数据一致.冗余字段应遵循: 不是频繁修改的字段. 不是 varcha ...

  4. NOIP 模拟 七十一

    最后一场多校模拟赛,好像是信心赛??不过考的不行..最近难题比较多,对题目的难度把握不够好,经常出现简单题跳过的现象. 100+100+20+40 T1 签到题(qiandao) 如果一个点的度数不是 ...

  5. Fortran学习笔记:03 数组(Array)

    Fortran学习笔记目录 书接上回:Fortran学习笔记:02 流控制语句 数组(Array) 定义数组 一维数组 program main implicit none integer :: i ...

  6. 数据库InnoDB和MyISAMYSQL的区别

    1.nnoDB支持事务,MyISAM不支持,这一点是非常之重要.事务是一种高级的处理方式,如在一些列增删改中只要哪个出错还可以回滚还原,而MyISAM就不可以了. 2.MyISAM适合查询以及插入为主 ...

  7. WPF实现聚光灯效果

    WPF开发者QQ群: 340500857  | 微信群 -> 进入公众号主页 加入组织 前言 效果仿照 CSS聚光灯效果 实现思路: 1. 设置底部Canvas背景色 #222222 . 2. ...

  8. Serverless 工程实践 | 零基础上手 Knative 应用

    作者|刘宇 前言:Knative 是一款基于 Kubernetes 的 Serverless 框架.其目标是制定云原生.跨平台的 Serverless 编排标准. Knative 介绍 Knative ...

  9. Java到底怎么学?

    你现在是不是想学Java,但很迷茫不知该从何下手,那么请认真看完这篇文章,希望对你有所帮助! 作为零基础刚刚接触Java的朋友们来说,我的建议还是先看视频,虽然有很多人说看视频学习慢,建议直接买优秀的 ...

  10. 【实验向】问题:假设计算机A和计算机B通信,计算机A给计算机B发送一串16个字节的二进制字节串,以数组形式表示:

    问题: 假设计算机A和计算机B通信,计算机A给计算机B发送一串16个字节的二进制字节串,以数组形式表示: unsigned char[16] = {0x3f, 0xa0, 0x00, 0x00, 0x ...