Java基础加强第二讲 反射(下)——数组的反射

具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class实例对象(此处比较与值无关)。例如,
在这里插入图片描述
此处,我再介绍两个方法,如下:

方法描述
public String getName()以String的形式返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称
public Class<? super T> getSuperclass()返回表示此Class所表示的实体(类、接口、基本类型或 void)的超类的Class

若代表数组的Class实例对象调用上述两个方法,会有什么结果呢?示例如下,
在这里插入图片描述
从上述代码运行的结果可知,代表数组的Class实例对象的getSuperclass()方法返回的父类为Object类对应的Class。
这里还要注意,基本类型的一维数组可以被当作Object类型使用,但不能当作Object[]类型使用;非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
在这里插入图片描述

Arrays.asList()方法处理int[]和String[]时的差异

在学集合框架中的Arrays工具类时,详情可参考第三十六讲 集合框架工具类,有结论:如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素。如果数组中的元素都是基本数据类型,那么会将该数组(例如[[I@15db9742])作为集合中的元素存在。
在这里插入图片描述
第一行代码会输出诸如[[I@15db9742]这样的内容,这是因为asList()方法按照JDK1.5的语法,将int[]当作一个Object对待;第二行代码会输出[a, b, c],这是因为asList()方法按照JDK1.4的语法,将String[]当作一个Object[]数组来对待。

数组的反射应用

我们可以使用Array工具类完成对数组的反射操作。例如,利用反射打印一个数组。

package cn.liayun.reflect;

import java.lang.reflect.Array;

public class ReflectArrayDemo {

	public static void main(String[] args) {
		printObject(new int[]{1,2,3});
		printObject(new String[]{"a","b","c"});
		printObject("xyz");
	}

	private static void printObject(Object obj) {
		Class clazz = obj.getClass();
		if (clazz.isArray()) {//如果是数组
			int len = Array.getLength(obj);//得到数组的长度
			for (int i = 0; i < len; i++) {
				//得到数组中的每一个元素
				System.out.println(Array.get(obj, i));
			}
		} else {
			System.out.println(obj);
		}
	}
}

或许我们会思考这样一个问题,怎么得到数组中的元素类型?想得到数组中的元素类型,是没有办法的,只能是得到某一个具体元素的类型,不能得到整个数组的元素类型。需要取出每个元素对象,然后再对各个对象进行判断,因为其中每个具体元素的类型都可以不同,例如

Object[] x = new Object[]{"abc", Integer.Max};

反射的应用——实现框架功能

什么是框架?

框架就好比开发商做的毛坯房,开放商将房子卖给用户,需要住户自己去装修,比如安装门窗。房子就是框架,用户将门窗插入框架中。框架与工具类的区别:框架调用用户提供的类,工具类则是被用户的类调用。

框架要解决的核心问题

我在写框架(房子)时,你这个用户可能还在上小学,还不会写程序呢?我写的框架程序怎样能调用到你以后写的类(门窗)呢?因为在写程序时无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象了,而要用反射方式来做。

综合案例

这里,我会采用配置文件加反射的方式创建ArrayList和HashSet的实例对象,然后比较观察运行后的结果差异。首要前提就是加载配置文件,例如config.properties,加载资源文件的方式有好几种,下面我会一一讲解。

  1. 第一种方式:首当其冲的一种方式,在Java Web开发中,利用API中XX类的getRealPath方法得到整个项目在硬盘上的真实位置(绝对位置),然后在项目内部找到资源文件config.properties的位置。记住,一定要用完整的路径,但完整的路径不是硬编码,而是运算出来的。
    例如,将资源文件放在工程的根目录下,一般我们是自己写代码这么干,但是在实际开发中不合适。
    在这里插入图片描述

  2. 第二种方式:一个类加载器能加载.class文件,那它当然也能加载classpath路径下的其他文件,既然它有如此能力,它没有理由不顺带提供这样一个方法,但它也只能加载classpath路径下的那些文件。
    在这里插入图片描述
    注意:直接使用类加载器加载资源文件时,不能以/打头。Hibernate/Struts2/Spring等框架用的配置文件都是放在classpath指定的目录下的,其内部就是使用类加载器加载配置文件。

  3. 第三种方式:Class类提供了一个便利方法getResourceAsStream,用加载当前类的那个类加载器去加载相同包目录下的文件,既可用相对路径又可用绝对路径。

    • 相对路径
      在这里插入图片描述
    • 绝对路径
      在这里插入图片描述
      在上面的路径中,最前面加斜杠表示绝对路径,斜杠代表根目录,不加斜杠表示相对路径,即相对于ReflectTest.class所在目录的路径,不管是相对还是绝对,其内部还是通过类加载器进行加载。

接着,使用反射的方式创建ArrayList或者HashSet的实例对象。

package cn.liayun.reflect;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.Properties;

import cn.liayun.domain.ReflectPoint;

public class ReflectTest {

	public static void main(String[] args) throws Exception {
		/*
		 * 得到资源文件的方式,方式一。
		 * getRealPath()://得到金山词霸整个项目的在硬盘上对应的真实(绝对)位置。
		 *               //金山词霸(整个项目)/资源文件内部地址
		 * 一定要记住用完整的路径,但完整的路径不是硬编码,而是运算出来的。
		 */
		//加载properties文件
//		InputStream ips = new FileInputStream("config.properties");
		
		/*
		 * 方式二。
		 * 用类加载器的方式加载配置文件。
		 * getResourceAsStream():在classpath指定的根目录下,逐一地去查找你要加载的文件。
		 * 但是只能读,不能存进去。
		 */
//		InputStream ips = ReflectTest.class.getClassLoader().getResourceAsStream("cn/liayun/reflect/config.properties");
		
		//用类提供的简便方法加载的时候,只需要写上配置文件的名字(用的是相对路径),不需要写上它的完整目录名。
//		InputStream ips = ReflectTest.class.getResourceAsStream("resource/config.properties");
		
		//用类提供的简便方法加载的时候,用的是绝对路径,只要打上/了,而是相对于classpath的根
		InputStream ips = ReflectTest.class.getResourceAsStream("/cn/liayun/reflect/resource/config.properties");
		
		Properties props = new Properties();
		props.load(ips);
		/*
		 * 释放本对象(ips)关联的操作系统资源,
		 * 本对象(ips)以后由JVM作为垃圾回收。
		 */
		ips.close();
		
		String className = props.getProperty("className");
		Collection collections = (Collection) Class.forName(className).newInstance();
		ReflectPoint pt1 = new ReflectPoint(3, 3);
		ReflectPoint pt2 = new ReflectPoint(5, 5);
		ReflectPoint pt3 = new ReflectPoint(3, 3);
		
		collections.add(pt1);
		collections.add(pt2);
		collections.add(pt3);
		collections.add(pt1);
		
		System.out.println(collections.size());
	}

}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
无论是工作学习,不断的总结是必不可少的。只有不断的总结,发现问题,弥补不足,才能长久的进步!!Java学习更是如此,知识点总结目录如下: 目录 一、 Java概述 3 二、 Java语法基础 5 数据类型 5 运算符号 14 语句 15 函数 15 方法重载(Overloadjing)与重写(Overriding) 16 数组 17 总结 18 三、 常见关键字 20 四、 面向对象★★★★★ 21 五、 封装(面向对象特征之一)★★★★ 23 六、 继承(面向对象特征之一)★★★★ 25 七、 接口(面向对象特征之一)★★★★ 28 八、 多态(面向对象特征之一)★★★★ 30 九、 java.lang.Object 31 十、 异常★★★★ 34 十一、 包(package) 37 十二、 多线程★★★★ 39 为什么要使用多线程 39 创建线程和启动 39 线程的生命周期 44 线程管理 45 线程同步 49 线程通信 52 线程池 58 死锁 64 线程相关类 65 十三、 同步★★★★★ 67 十四、 Lock接口 70 十五、 API 71 String字符串:★★★☆ 71 StringBuffer字符串缓冲区:★★★☆ 73 StringBuilder字符串缓冲区:★★★☆ 74 基本数据类型对象包装类★★★☆ 75 集合框架:★★★★★,用于存储数据的容器。 76 Collection接口 77 Iterator接口 78 List接口 78 Set接口 80 Map接口 81 把map集合转成set的方法 82 使用集合的技巧 83 Collections--集合工具类 83 Arrays—数组对象工具类 84 增强for循环 85 可变参数(...) 86 枚举:关键字 enum 86 自动拆装箱 86 泛型 87 System 89 Runtime 90 Math 90 .Date:日期类,月份从0—11 92 Calendar:日历类 93 十六、 IO流:用于处理设备上数据 ★★★★★ 94 IO流的概念 95 字符流与字节流 98 流对象 101 File类 102 Java.util.Properties 103 介绍IO包中扩展功能的流对象 103 十七、 网络编程 110 网络基础之网络协议篇 111 UDP传输 124 TCP传输 126 十八、 反射技术 127 十九、 Ajax原理及实现步骤★★★★★ 130 Ajax概述 130 Ajax工作原理 130 Ajax实现步骤 130 详解区分请求类型: GET或POST 131 $.ajax标准写法 134 二十、 正则表达式:其实是用来操作字符串的一些规则★★★☆ 135 二十一、 设计模式★★★★★ 136 设计模式简介 136 单例设计模式:★★★★★ 156 工厂模式★★★★★ 159 抽象工厂模式★★★★★ 163 建造者模式 170 原型模式 177 适配器模式 182 桥接模式 188 过滤器模式 192 组合模式 193 装饰器模式★★★★★ 196 外观模式 201 享元模式 204 代理模式★★★★★ 208 责任链模式 212 命令模式 216 解释器模式 219 迭代器模式 222 中介者模式 224 备忘录模式 226 观察者模式 230 状态模式 233 空对象模式 236 策略模式★★★★★ 238 模板模式 240 访问者模式 244 设计模式总结★★★★★ 247 二十二、 Java其他总结 248 Java JVM知识点总结 248 equals()方法和hashCode()方法 270 数据结构 273 Array方法类汇总 304 Java数组与集合小结 305 递归 309 对象的序列化 310 Java两种线程类:Thread和Runnable 315 Java锁小结 321 java.util.concurrent.locks包下常用的类 326 NIO(New IO) 327 volatile详解 337 Java 8新特性 347 Java 性能优化 362

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李阿昀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值