基础加强-java反射

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------

                               基础加强-java反射
                               
一,Class类 (比较时用==进行比较字节码在内存中只有一份)
注:我们平时定义类的关键字class与Class类不是一回事,class 是关键字用于定义类的,而Class类是用描述class类的。而它的实例对象
就是.class文件 。比如:Persion 类是用来描述人这个类的,而new Persion( )就 是这个类的实例对象。而Class类也是用class关键字来定义 的。                             
1,介绍Class类:
java类用于描述一类事件的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则是由这个类的实例对象来确定的,不同
的实例对象有不同的属性值,java程序中的各个java类,它们 是属于同一类事物,也是可以用一个类描述这类事物的。这个类的名字就是Class类
也就是说Class类是用来描述java中的类

二,Class类中的方法
String getName() :返回此对象(字节码)的名字
Method[] getMethods():返回此对象中的所有方法对象(将方法也封装成一个对象)的数组
Class<?>[] getInterfaces():得到该类实现的所有接口的数组,(接口也是一个Class对象,编译时也会产生.class文件)
boolean isPrimitive():判断此字节码是否是原始类型(是不是基本类型)基本数据类型包装类不是基本数据类型,数组也不是。
boolean isArray():判断此字节码对象是否是一个数组类型 
Package getPackage();返回此对象所在的包的对象
Field  getField(String name):反回指定名字的子段对象获取全局变量(可见的变量用public修饰的,用private ,和默认权限的变量都是获取不到的。)
Field[] getFields():返回此对象中的所有子段对象的数组
Field getDeclaredField(String name):取出指定名字的字段对象,可见的,不可以见都能取出(不管什么的样的修饰符都可以获取)
Constructor getConstructor(Class... parameterTypes):获取某一个构造方法(此方法的参数为一个形势参数的class对象)使用了1.5新特性可变参数
Constructor [] getConstructors():获取此对象中的所有的构造方法
T newInstance():返回此class对象的实例对象,其实是调用Constructor中newInstance方法参数为空返回的对象一样
Method getMethod(String methodName,Class... parameterTypes);获取指定某个对象上指定的方法对象参数为:方法名,方法参数类型的class对象
Class getSuperclass():返回此对象的父类的class对象
ClassLoader getClassLoader():获取加载class对象的类加载器
boolean isAnnotationPresent(Class annoation):判断此class对象上是否在指定的注解,参数为注解的class对象
Object getAnnotation(Class annotation):返回此注解class对象的实例对象

.Class类没有构造方法,它的实例对象就是内存中的一份字节码
字节码:将源文件编译生成二进行代码(字节码),存放在硬盘上。当使用此类时,将此类的二进行代码加载进内存生成字节码对象

四,获取一个类的Class对象方法


1,类型名.class  返回一个Class对象

2,这个类的实例对象.getClass(),也会返回一个Class对象。getClass()方法定义在Object中

3,Class类中的一个静态方法: static Class forName(类的名字):如 Class.forName("java.lang.String")会返回一个string类的字节码对象
forName的作用:当jvm中没有字节码时,调用类加载器将硬盘上的字节码文件加载进行jvm并缓存起来
得到类的字节码有两种情况 :
1,此类的字节码已经加载到了内存中
 对象.getClass();
2,此类的字节码没有加载到内存中
Class.forName(className);

五,九个预定义的Class实例对象

int short byte String boolean double folat char void 

预定义Class实例对象:个人理解可能就是它们字节码已经存在于jvm中的,不会每次都去使用类加载器去硬盘上加字节文件到jvm中
注;基本数据包装类的Class对象与基本数据类型的Class对象不相同的。基本数据包装类有一个常量值TYPE 此常量值会返回此基本类型包装类
所包装的类型的字节码对象。数组也是一种类型,不是原始类型。

总:总之,只要是在源程序中出现的类型,都有各自的Classic实例对象,如:int[] void 

一些验证代码:
public class ReflectTest {

public static void main(String[] args){

//获取一个class对象的三种方法
//第一种:使用每个类具有一个属性吧.class
Class<ReflectTest> class1 = ReflectTest.class;
//第二种:使用每个一个对象都有的方法getClass()方法,此方法定义在Object类中
Class<? extends ReflectTest> class2 = new ReflectTest().getClass();
//第三种:使用Class类的中静态方法将此类 加载进内存中
Class<ReflectTest> class3 = null;
try {
  class3 =  (Class<ReflectTest>) Class.forName("day01.ReflectTest");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
throw new RuntimeException("没有找到这个类!");
}
//判断一下获取的这三个class对象是否是一样的。
System.out.println(class1 == class2 );//true
System.out.println(class2 == class3);//true
//Class类中一些方法

//获取class 对象的名字
System.out.println(class1.getName());//day01.ReflectTest
//判断此对象是不是基本数据类型
System.out.println(class1.isPrimitive());//false
//判断此对象是不是一个数组类型的
System.out.println(class1.isArray());//false

//判断基本数据类型包装类的class对象是不是和基本数据类型的class对象是不是同一个对象
System.out.println(Integer.class == int.class);
//基本数据类型包装类的一个TYPE属性可以获取它所包装的类型的class对象,判断一下此类型与基本数据类型class对象是否相同
System.out.println(int.class == Integer.TYPE);//true
//难验证基本数据类型的数组和基本数据类型是不是使用同一个class对象
System.out.println(int[].class.isPrimitive());//false
//验证基本数据类型包装类与基本数据包装类的数组
System.out.println(Integer[].class.isPrimitive());//false
}
}


六,反射的概念
1,反射:就是把java类中的各种成分映射成相应的java类,例如一个java为中用一个Class类的对象来表示,一个类中的组成部分:成员变量
方法,构造函数,包等等信息也用一个个的java类来表示 ,表示 java类的Class类显然要提供一系列的方法,来获得其中的变量,方法,
构造方法,修饰符,包等信息,这些信息就是用相应类的实例对象来表示,它们是Field Method Constructor,等。一个类中的的每个成员都
可以相应的反射成api类的一个实例对象来表示。通过调用Class类的方法可以得到这些实例对象

七,Constructor类(构造方法类)

1,方法:
int getModifiers():获取此构造方法的修饰符。
Class getDeclaringClass():获取此构造方法所属的类
T newInstance(Object... obj):可以建立该类的实例对象,使用了可变参数
String getName():会返回此构造函数的名字
Class[] getParameterTypes():返回此构造方法中所有的参数类型列表



八,Field类 (成员变量)代表字节码对象上的一个变量并不代表某一个对象上的变量

1,方法:
Object  get(Object obj);返回,Object中field对象所对的值。参数为要取出的变量所在的对象。(也就是说你通过反射会得到一个Field对象,
这个对象就是Object(你操作的对象)中的一个变量,这个方法就是返回这个Object(你操作的对象)的变量的值 )

void setAccessible(boolean):设置访问权限,当class对象调用getDeclareField()方法时,使用此方法进行权限设置
Class getType():获取该字段的类型

set(Object obj,Object value):对某个对象上的某个字段进行设置值。如:nameField.set(new Persion(),"ksks"),对persion对象上的
name字段进行值的设置nameField代表persion字节码上的变量,改变的是你传入对象的变量的值。字节码中的值是不会改变的

九,Method类  

1,对象调用方法与对象没有关系
2,方法:
Object invoke(Object obj,Object... args):将此method对象方法作用到obj对象上,args为实际要传入的参数。当实际传入的obj对象为null时说明
此方法为静态方法。此方法会返回:参数 args 在 obj 上指派该对象所表示方法的结果(也就是说返回obj调用method对象的结果)
Type[] getGenericParameterTypes():返回此方法参数类型的数组
Type getGenericReturnType();返回此方法返回值的泛型类型
Class<?>[] getParameterTypes():返回此方法所有参数列表

十,调用main(String[] args)方法
为什么要使用反射来执行main方法?
因为main方法是静态的可以通过类名进行调用,可是当我们不知道此类类名是什么时,或这上类名是一个函数运算完的结果,所以这时我们可以使用反射来
完成此类的加载和运行
1,参数传递时的问题?
启动java程序 的main方法的参数是一个字符串数组,即public static void main(String[] args)通过 反射方式来调用这个mainyyjf 
时,如何为invoke方法传递参数呢,按jdk1。5语法,整个数组是一个参数。而按jdk1.4的语法,数组中的每个元素对应一个参数。当把
一字符串数组作为参数传递给invok方法时,由于jdk1.5要兼容jdk1.4的语法。所以会jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数
所以。在给main方法传递参数时,不能使用代码new String[]{"kdfj","ksdf"}javac 只把它当3作jdk1.4的语法进行理解,而不把它
作jdk1.5的语法理解。因此会出现参数类型不对的问题。解决办法有两种:1,传入new Object[]{new String[]{"kdf","dkfj"}}
2,(Object)new String[]{"dkfj","dkfj"}; 


十一,数组与反射
1,如果你使用反射的数组是相同的类型且维度是相同(不是数组的长度是维度 ),则反射出来的是同一个class对象
如:
int[] a1= new int[2];int[] a2 = new int[3]; int[][] a3 = new int[2][3] String[] a4 = new String[2];
System.out.println(a1.getClass() == a2.getClass());输出:true
System.out.println(a1.getClass() == a3.getClass()); false
System.out.println(a1.getClass() == a4.getClass()); fale
        System.out.println(a1.getClass().getName()); 输出:[I
        
   2,所有数组的父类都Object
    int[] i = new int[2]; Object[] obj = i;//是不是成产的,int类型不是对象
   
    3,注意:Arrays类中的aList(T..args)方法,此方法在jdk1.4版本是aList(Ojbect[] obj)所以在传值进要注意。当传入的参数为int[]时,jdk1.4
    的语法处理不了,所以要用jdk1.5的语法进行处理。将int[] 做为一个对象进行传递,而当传入的是Sring[] 时,jdk1.4的语法是可以解析的,
    将其打开,分别做为一个参数进行传递,所以运行没有问题,可以正常输入原来sting[]中的数据
   
十二,对数组反射的类(Array类)

1,方法:
static int  getLength(Object obj):获取传入对象的长度
static Object get(Object array,int index):获取array中第几个元素

十三,哈希算法:
哈希算法来提高 从集中查找元素的效率,这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希码,可以将哈希码分组,
每组分别对应某个存储区域,根据一个对象的哈希码可以确定该对象应该存储在哪个区域HashSet就是采用哈希算法存取对象的集合,它
内部采用对某个数字n进行取余的方式对哈希码进行分组和划分对象的存储区域

两个相同的对象都算出了Hash值,但它们取余的结果不同,被放在了不同的区域里了。

注意:当一个对象被存储进hashSet集合中以后,就不能修改这个对象中的那些参与计算的哈希值的字段了,否则,对象修改后的哈希值
与最初存储进HashSet集合中的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合
中检索对象,也将返回找不到对象的结果, 这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露。(对象不在使用而且也没有被释放)
如以下代码:

import java.util.*;


class Demo{

public static void main(String[] args){

//建立一个集合
Collection<Persion> collection = new HashSet<Persion>();
//在外面先建立引用,
Persion p1 = new Persion("hshs",23);
Persion p2 = new Persion("hshs",24);
Persion p3 = new Persion("ksk",22);
//将persio对象存入集合中
collection.add(p1);
collection.add(p2);
collection.add(p3);

System.out.println(collection.size());//此集合长度为3;
//改变其中一个persion对象的值,
p1.name="kd";
//删除一个p1这个对象
collection.remove(p1);
System.out.println(collection.size());//此时集合的长度仍为3 这样就造成了内存泄露问题

}
}
class Persion{

public  String name;
public int age;

public Persion(String name,int age){

this.name = name;
this.age = age;
}
//复写hashCode方法
public int hashCode(){

return name.hashCode()+age ;
}
}

---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值