计算硬盘哈希 时间复杂度值时,为什么每次不一样

为什么硬盘上写的与格式化后的容量显示不一样-什么电脑磁盘显示容量和实际不
没有你要的?请搜索……
你现在正在浏览:
为什么硬盘上写的与格式化后的容量显示不一样 什么电脑磁盘显示容量和实际不
为什么硬盘上写的与格式化后的容量显示不一样
比如买的时候写的是120G,但格式化后系统中显示的是118G,为什么?
对于第一种情况? 数据写入的时候,闪存芯片内部需要有至少一个物理块(Block)作为交换块使用。 除了上述原因之外,这些功能实际上需要占用闪盘中的部分物理块来存放特殊配置信息或数据。 另外,有些朋友发现自己的闪盘在使用一段时间后,再次格式化,其容量竟然会自动变小了。这又是什么原因呢,细心的话,会发现产品的实际容量往往要比其标称容量小硬盘格式化容量竟然会变小,与硬盘一样。 最后还有一点,容量越来越小。不过,往往设定1KB=1000B---&动存储解决方案,个别厂商在其产品中加入了诸如保密,因为没有预留空间,闪存在读写时交换块的损耗相当大,于是就会出现容量越来越小的情况。对于第二种情况,厂商在设计时已经预留部分物理块,比如选择1024个物理块中的1000个作为数据存储使用,其余24个物理块(包括坏块)用作缓冲交换块部分。 每次上电后,这些区域也要占用闪存空间,一般需要占用几百KB? 原因如下,基本不会出现容量越来越小的情况,存储单元的逻辑地址和物理地址需要重新对照,交换块并不是固定的某一区块,因而每一个物理块进行读写操作的几率几乎相同,不会出现哪一个物理块过早被损坏的现象。这就产生了存储设备标配容量和实际使用容量出现差异的情况。 在闪存的存储单位中,一个物理块包含若干个物理页。因此写数据时、FAT文件分配表和ROOT目录区等,闪盘作为一项比较常用的移&lt,当闪存芯片的某个物理存储区块达到读写指定的最高次数时,那么该块区将被设定为不再使用的区域,所以闪盘有可能在极度频繁地使用下。而操作系统的换算则为1KB=1024Bytes:1。这是因为闪存的写操作很特殊,目前多数闪盘产品已经可以保证擦写百万次以上的使用寿命。 多数闪盘产品可以保证百万次以上的擦写 目前市场上的闪存产品包括两类,闪存盘也是采用FAT文件系统,而FAT文件系统包括MBR主引导分区、1MB=1000KB、1GB=1000MB,需要有一个空的、可以使用的交换块来存放不需要被擦除的数据。由于闪存的充放电特性. 未预留缓冲空间的. 预留有缓冲空间的,而在操作系统中格式化后其实际容量可能只有61.8MB。那么这里少的2.2MB的容量到哪儿去了?难道厂商卖给我们的产品“短斤少两”? 这2.2MB的空间并非凭空蒸发了,而主要是操作系统识别与硬件设备生产厂商两者容量计算公式上的不同所致。生产厂商为了计算方便。 通常厂商会在闪盘内部做一个读写次数的计数,64MB闪盘的容量应该为62.5MB,以此类推。对于预留缓冲空间的闪盘来说,使得它的读写次数有物理上的限制。举个例子,一个全新的闪盘产品标称容量为64MB、QQ聊天记录备份等功能。 由此推算可知128MB闪盘的实际容量理论上应为125MB,而擦除的最小单位是一个物理块,但写数据的最小单位却是一个页(Page),必须是先擦除,然后才能写入数据: 我们在平时使用闪盘时、1MB=1024KB、1GB=1024MB。此外,由于闪存芯片本身在制造时的问题,闪存介质允许有坏块(Bad Block)的存在,这些坏块不能被使用,也不算做有效容量;2
格式化有时候会缩小容量的
那是必须的 都会这样的,放心吧 没问题的,留给磁盘使用了。
为什么硬盘上写的与格式化后的容量显示不一样:
硬盘格式化容量竟然会变小? 原因如下: 我们在平时使用闪盘时,细心的话,会发现产品的实际容量往往要比...
硬盘格式化有什么好处与坏处?:
格式化才能用 格式化还会做下对齐,尤其是对固态硬盘有用,机械就算了没用 坏处就是容易伤硬盘,所以一般...
什么是格式化? 为什么电脑的硬盘格式化后容量变小了?:
简单的说,格式化就是把一张空白的盘划分成一个个小的区域,并编号,供计算机储存,读取数据。没有这个工作...
将硬盘格式化有什么后果啊:
1、格式化是指对磁盘或磁盘中的分区进行初始化的一种操作,这种操作通常会导致现有的磁盘或分区中所有的文...
电脑硬盘格式化后,为什么显示已用90多M,容量是和可用是一样的。那已用的是什么啊。:
用了90多兆可见你的硬盘很大,是格式化成的NTFS格式吧?占的那90多兆是这种文件格式(NTFS,F...
移动硬盘格式化有那几个格式?每个格式代表什么?:
分区格式: 1、fat16 对电脑老“鸟”而言,对这种硬盘分区格式是最熟悉不过了,我们大都是通过这种...
EXFAT格式 会抹掉硬盘里所有的内容吗?:
不在了,这个就相当于我们常用的格式化
电脑格式化是什么意思?:
  1、格式化是是把一张空白的盘划分为1个小区域然后在编号,这样提供计算机保存来读取数据。如果没有这...
格式化硬盘以后会有记录吗:
一般情况下是不会有记录的,但专业恢复数据软件,尤其是高保密级别的(例如用于国防'军工方面的)专用恢复...
也许你也感兴趣的内容商品名称:
京东价:暂无报价
评价得分:
咨询内容:
你好,为什么包装和上的PN值和移动硬盘上的PN值不一样?我是不是可以理解为我买的是假?谢谢
京东回复:
您好!京东都是正品奥,关于PN码,官方没有提供此类信息,为保证您获得准确而专业的支持,建议直接致电官方进行相关咨询。谢您对京东的支持!祝您购物愉快!
发表咨询:
声明:您可在购买前对产品包装、颜色、运输、库存等方面进行咨询,我们有专人进行回复!因厂家随时会更改一些产品的包装、颜色、产地等参数,所以该回复仅在当时对提问者有效,其他网友仅供参考!咨询回复的工作时间为:周一至周五,9:00至18:00,请耐心等待工作人员回复。
咨询类型:
库存及配送
发票及保修
促销及赠品
京东承诺:商品均为原装正品行货,自带机打发票,严格执行国家三包政策,享受全国联保服务。
功能咨询:咨询商品功能建议您拨打各品牌的官方客服电话,以便获得更准确的信息。
发货时间:现货:下单后一日内即可发货;在途:一般1-2天发货; 预订:一般1-6天可发货;无货:已售完,相应物流中心覆盖地区内的用户不能购买
运&&&&费:如需查看快递运输收费标准及免运费规则,
货到付款:如需查看开通货到付款地区及运费,
上门自提:上门自提不收取运费,如需查看全部自提点位置、地图、注意事项,
物流中心:京东商城拥有北京、上海、广州三个物流中心,各物流中心覆盖不同的城市,
限&&&&额:如需查看各银行在线支付限额,
大额支付:快钱支付中的招行、工行、建行、农行、广发支持大额支付,最高单笔一次支付10000元
分期付款:单个商品价格在500元以上,可使用中国银行、招商银行发行的信用卡申请分期付款,
货到付款:如需查看开通货到付款地区及运费,
京东承诺:商品均为原装正品行货,自带机打发票,严格执行国家三包政策,享受全国联保服务。
发票类型:京东商城所售商品均自带机打发票,在提供相关企业资料证明后,可申请开取增值税发票。
退 换 货:京东商城为您提供完善的退换货服务,
咨询内容:
多品类齐全,轻松购物
快多仓直发,极速配送
好正品行货,精致服务
省天天低价,畅选无忧还没有帐号? 赶紧
用户版块帖子
为什么一块硬盘不同分区速度差这么多
UID:1937561
在线时间12小时
M币-465专家-1
同一块硬盘分别测试四个分区,速度差别很大,如图,这是为什么?=740) window.open('http://img.mydigit.net/Mon_38c47216.png?46');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="为什么一块硬盘不同分区速度差这么多" alt="为什么一块硬盘不同分区速度差这么多">=740) window.open('http://img.mydigit.net/Mon_d9881087a.png?46');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="为什么一块硬盘不同分区速度差这么多" alt="为什么一块硬盘不同分区速度差这么多">=740) window.open('http://img.mydigit.net/Mon_ed12376d12.png?46');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="为什么一块硬盘不同分区速度差这么多" alt="为什么一块硬盘不同分区速度差这么多">=740) window.open('http://img.mydigit.net/Mon_57cebc8b6.png?46');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="为什么一块硬盘不同分区速度差这么多" alt="为什么一块硬盘不同分区速度差这么多">
UID:1766910
在线时间389小时
M币4691专家8
磁盘外圈,内圈问题吧不同位置,线速度不一样的。
UID:1207399
在线时间4374小时
M币1879专家19
应该是磁头摆动内外圈的问题,毕竟磁头与盘体之间是均匀线速度与均匀角速度之间的速度关系差距吧
UID:805500
在线时间4400小时
M币4813专家85
硬盘是从外圈到内圈依次划分磁道的,在相同转速下,外圈线速度高,读写也就快
UID:74432
在线时间31小时
M币18专家1
跟四千对齐所设的数字有关,2048&&速度不错
UID:74432
在线时间31小时
M币18专家1
不好意思,答错了,怎么删啊
UID:1179202
在线时间57小时
M币800专家4
学习了技巧
访问内容超出本站范围,不能确定是否安全
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
您目前还是游客,请
&回复后跳转到最后一页
Code by , Time now is:08-26 21:41, Total 0.188697(s) query 7,
Gzip enabled&wuhaisongwangyi
、期待与您交流! -------
本章内容:
一:JavaBean及BeanUtils工具包的使用
二:1.5新特性:注释
三:1.5的新特性:泛型
四:加载器
五:代理和spring可配置AOP框架实例
第一部分:&JavaBean
& & JavaBean是一种特殊的Java类,主要用于传递数据信息,这种Java类中的方法主要用于访问私有的字段,且方法符合某种特殊的命名规则。
& & &它是一种特殊的Java类,其中的方法符合特殊的规则。只要一个类中含有get或is和set打头的方法,就可以将其当做JavaBean使用。
& &如果要在两个模板之间传递多个信息,可将这些信息封装到一个JavaBean中,这种JavaBean的实例对象通常称之为值对象(Value Object,简称VO),这些信息在类中用私有字段来储存,如果读取或设置这些字段的值,则需要通过一些相应的方法来访问。
avaBean的属性是根据其中的setter和getter方法来确定的,而不是依据其中的变量,如方法名为setId,则中文意思是设置Id,getId也是如此;去掉set或者get前缀,剩余部分就是属性名称。如果剩余部分的第二个字母小写,则把剩余部分改为小写。
如:setId()---&属性名--&id
isLast()属性名---&last
setCPU的属性名是----&CPU
getUPS的属性名是---&UPS
& & & & 总之,一个类被当作javaBean使用时,JavaBean的属性是根据方法名推断出来的,它根本看不到java类内部的成员变量。
一个符合JavaBean特点的类当做普通类一样可以使用,但是把它当做JavaBean类用会带来一些额外的好处:好处如下:
& & & &1. 在Java EE开发中,经常要使用到JavaBean。很多环境就要求按JavaBean方式进行操作,别人都这么用和要求这么做,那你就没什么挑选的余地!
& & & &2. JDK中提供了对JavaBean进行操作的API,这套API称为内省,若要自己通过getX的方式来访问私有x,可用内省这套API,操作JavaBean要比使用普通的方式更方便。
javaBean示例代码:
import java.beans.IntrospectionE
import java.beans.PropertyD
import java.lang.reflect.InvocationTargetE
import java.lang.reflect.M
public class Test {
public int x = 10;
private int y = 20;
public int getX() {
public void setX(int x) {
public static void main(String[] agrs) throws Exception {
Test t = new Test();
String beenX = &x&;
getProperty(t, beenX);
setProperty(t, beenX, 30);
private static void setProperty(Test t, String beenX, Object value)throws Exception {
//将要操作的属性和对象与PropertyDescriptor相关联
PropertyDescriptor p = new PropertyDescriptor(beenX, t.getClass());
//获取设置属性的set方法
Method methodSet = p.getWriteMethod();
//调用方法将设置值
methodSet.invoke(t, value);
//在获取取值的get方法
Method methodGet = p.getReadMethod();
//调用get的方法获取属性
Object obj = methodGet.invoke(t);
//通过打印,就证实了刚刚调用的set的方法已经将值设进去了。
System.out.println(obj);
private static void getProperty(Test t, String beenX) throws Exception {
//将要操作的属性和对象与PropertyDescriptor相关联
PropertyDescriptor p = new PropertyDescriptor(beenX, t.getClass());
//在获取取值的get方法
Method methodGet = p.getReadMethod();
//调用get的方法,返回属性的值,
Object obj = methodGet.invoke(t);
//通过打印得到了属性的值
System.out.println(obj);
BeanUtils工具包:
BeanUtils等工具包都是由阿帕奇提供的
还需要一个:logging因为BeanUtils使用到logging的内容
BeanUtils设置的参数都是以字符串的形式设置进去的,取的时候也是以字符串的形式去出来,BeanUtils工具包还可以通过Map集合进行转换,可以通过键值对的形式设置进去。
另外:PropertyUti是java的api提供的一个工具包,这个工具包可以根据本来的类型来设置和获取的操作,它不改变你的类型,也就是说如果想要帮自动转换成String类型的话可以用BeanUtils工具包,不需要转换的话可以用PropertyUtil工具包
工具包的导入方法:
下载好后将BeanUtils的jar和logging的jar包复制到工程内,件一个包来存放,然后并在jar上点右键--选择Builder Path---Add to BiuldPath,即可。这样做了之后就会跟着项目一走了。
第二部分:1.5新特性:注释
注解(Annotation)相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。以后,javac编译器、开发工具和其他程序可以用反射来了解你的类及各种元素上有无何种标记,看你有什么标记,就去干相应的事。标记可以加在包,类,字段,方法,方法的参数以及局部变量上。
标志的格式:
格式:@注解类名。
在java的api提供的三个注释类:
Deprecated://过时
用 @Deprecated 注释的程序元素,不鼓励程序员使用这样的元素,通常是因为它很危险或存在更好的选择。在使用不被赞成的程序元素或在不被赞成的代码中执行重写时,编译器会发出警告
Override://覆盖
表示一个方法声明打算重写超类中的另一个方法声明。如果方法利用此注释类型进行注解但没有重写超类方法,则编译器会生成一条错误消息。
SuppreesWamings://可以设置属性,使编译器不警告
指示应该在注释元素(以及包含在该注释元素中的所有程序元素)中取消显示指定的编译器警告。注意,在给定元素中取消显示的警告集是所有包含元素中取消显示的警告的超集。例如,如果注释一个类来取消显示某个警告,同时注释一个方法来取消显示另一个警告,那么将在此方法中同时取消显示这两个警告。&
根据风格不同,程序员应该始终在最里层的嵌套元素上使用此注释,在那里使用才有效。如果要在特定的方法中取消显示某个警告,则应该注释该方法而不是注释它的类。
RetentionPolicy
注解的生命周期的三个阶段:也就是三个属性值的设置
注释保留策略。此枚举类型的常量描述保留注释的不同策略。它们与 Retention 元注释类型一起使用,以指定保留多长的注释
CLASS :&编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。 //也是默认值
RUNTIME :&编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。&
SOURCE: 译器要丢弃的注释枚举常量
& & static RetentionPolicy valueOf(String name) :返回带有指定名称的该类型的&
& 注释类型 Target//可以使注释类使用的范围
指示注释类型所适用的程序元素的种类。如果注释类型声明中不存在 Target 元注释,则声明的类型可以用在任一程序元素上。如果存在这样的元注释,则编译器强制实施指定的使用限制。 例如,此元注释指示该声明类型是其自身,即元注释类型。它只能用在注释类型声明上:&
& & @Target(ElementType.ANNOTATION_TYPE)
& & public @interface MetaAnnotationType {
& & & & ...&
&此元注释指示该声明类型只可作为复杂注释类型声明中的成员类型使用。它不能直接用于注释:&
& & @Target({})&
& & public @interface MemberType {
& & & & ...
&这是一个编译时错误,它表明一个 ElementType 常量在 Target 注释中出现了不只一次。例如,以下元注释是非法的:&
& & @Target({ElementType.FIELD, ElementType.METHOD, ElementType.FIELD})
& & public @interface Bogus {
& & & & ...
类:java.lang.annotation.ElementType:
枚举常量摘要&
ANNOTATION_TYPE&
& & & & & 注释类型声明&
CONSTRUCTOR&
& & & & & 构造方法声明&
& & & & & 字段声明(包括枚举常量)&
LOCAL_VARIABLE&
& & & & & 局部变量声明&
& & & & & 方法声明&
& & & & & 包声明&
PARAMETER&
& & & & & 参数声明&
& & & & & 类、接口(包括注释类型)或枚举声明&
static ElementType valueOf(String name)&
& & & & & 返回带有指定名称的该类型的枚举常量。
元注解:@Retention是控制注解的生命周期的注解,声明周期分三个阶段原文件:SOURCE,运行:RUNTIME,默认阶段class阶段:CLASS,
元注解:@Target是控制注解的使用范围的一个注解:其具体属性看上面的@Target的字段
注解的属性:
1.可以是八种基本数据类型
2.可以是枚举
3.可以是注解
4.可以是String类型
5.也可以是上面几种的数组
& 另外:value是一个特殊的属性值,当只有value属性时使用注解的value的属性值时,可以不用写等号赋值,直接写值即可。
代码示例:
下面定义了三个类:一个是注解类:MyA一个使用注解的类:Use_Annotation,一个是对使用注解的类进行反射的测试类:Anatation_Text
import javax.lang.model.util.E
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT;
import javax.xml.crypto.dsig.keyinfo.RetrievalM
//@Retention是元注解,是控制生命周期的元注解,RetentionPolicy是枚举有三个取值对应这个元注解的的三个生命周期
//生命周期三个阶段:原文件:SOURCE,运行:RUNTIME,默认阶段class阶段:CLASS,
@Retention(RetentionPolicy.RUNTIME)//如果不是RUNTIME值反射是反射不到的
//@Target也是元注解,可以控制注解可以放在类的什么位置:可以在方法:@Target(ElementType.METHOD)
@Target({ElementType.METHOD,ElementType.TYPE})//这个可以在类和方法上
public @interface MyAnnotation {
String value() ;//特殊属性:只有value值是可以省略属性加=号直接赋值&
String color()default &www&;
int[] arr()default{3,23,23};//数组类型的
//EnumTest.TrafficLamp lamp() default EnumTest.TrafficLamp.RED;//枚举类型
//MetaAnnotation annotationAttr() default @MetaAnnotation(&kk&);//注解类型
package heima.
@MyAnnotation(color=&ren&,value=&kdl&,arr={6,34,4})//当数组属性只有一个元素可以不有加大阔号,
//@MyAnnotation(annotationAttr=@MetaAnnotation(&www&))
public class Use_Annotation {
@MyAnnotation(&只有value值是可以省略属性加=号直接赋值&)
public void run(){
package heima.
public class Anatation_Text {
public static void main(String[] args) throws Exception {
Class clazz=Class.forName(&heima.anotation.Use_Annotation&);//获取使用注释的类
System.out.println(clazz.isAnnotationPresent(MyAnnotation.class));
if (clazz.isAnnotationPresent(MyAnnotation.class)) {
System.out.println(clazz.getName());
//获取使用注解的类的注解
MyAnnotation annotation=(MyAnnotation)clazz.getAnnotation(heima.anotation.MyAnnotation.class);
System.out.println(annotation.color());//注解的属性通过访问方法那样访问
System.out.println(annotation.value());
System.out.println(annotation.arr().length);//
第三部分:1.5的新特性:泛型
泛型概念:是提供给java编译器使用的可以限定集合中的输入类型。让编译器挡住了原程序的非法输入,编译器编译带类型说明的集合时会去掉类型的信息,使程序运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样,由于编译生成的字节码会去掉泛型的类型的信息,只能跳过编译器,就可以往某个泛型集合中加入其他类型的数据,例如:反射得到集合,在调用集合的add的方法。
代码示例:
反射的手段,将定义Strin的泛型的集合,装Integer类型的元素
public class Test {
public static void main(String[] agrs) throws Exception {
ArrayList&String& arrl=new ArrayList&String&();
Class clazz=arrl.getClass();
Method method=clazz.getMethod(&add&,Object.class);
method.invoke(arrl, 34);
System.out.println(arrl);
二:泛型定义中的术语:
& & & & 如:ArrayList&E&类和ArrayList&Integer&
& & & & 1.ArrayList&E&整个称为泛型类型
& & & & 2.ArrayList&E&中的E称为类型变量或类型参数
& & & & 3.整个ArrayList&Integer&称为参数化类型
& & & & 4.ArrayList&Integer&中的Integer称为类型参数的实例或实际类型参数
& & & & 5.ArrayList&Integer&中的&&称为typeof
& & & & 6.ArrayList称为原始类型
四:参数化类型与原始类型的兼容性
& & & & 1.参数化类型可引用一个原始类型的对象,编译只是报警告。
& & & & 如:Collection&String&coll = new Vector();
& & & &2.原始类型可引用一个参数化类型的对象,编译报告警告
& & & & 如:Collectioncoll = new Vector&String&();
& & & & 原来的方法接受一个集合参数,新类型也要能传进去。
3.参数的类型不考虑类型参数的继承关系:
& & & & Vector&String& v = newVector&Objec&();//错误的
& & & & 不写Object没错
& & & & Vector&Objec& v = newVector&String&();//错误的
4.在创建数组示例时,数组的元素不能使用参数化的类型,例如:下面的语句有错误:
& & & & 如:Vector&Integer&vectorList[] = new Vector&Integer&[10];//错误的
下面代码会报错吗?
Vector v=new Vector&String&()//不会
Vector&Object&v=v1;//不会
三:泛型的通配符:
泛型的限定:
? 通配符。也可以理解为占位符。
泛型的限定:
? extends E: 可以接收E类型或者E的子类型。上限。
正确:vector&? extends Number& x=new Vector&Integer&;
错误:vector&? extends Number& x=new Vector&String&;
? super E: 可以接收E类型或者E的父类型。下限
正确:Vector&? super Integer& x=new Vector&Number&;
错误:Vector&? super Integer& x=new Vector&Number&;
注:限定通配符总是包括自己
泛型限定的示例代码:
定义两个类Student类和Worker类,这两个类都继承Person类,目的用于创建对象存进TreeSet集合,另外定义一个带泛型
import java.util.I
import java.util.TreeS
MyComp&Person&的比较器
class Person{
Person(String name,int age){
this.name=
class Student extends Person{
Student(String name ,int age){
super(name,age);
class Worker extends Person{
Worker(String name ,int age){
super(name,age);
class MyComp implements Comparator&Person&{//定定义比较器,这要是Person类型的都可以比较
public int compare(Person o1, Person o2) {
return pareTo(o2.name);
class Test {&
public static void main(String[] agrs) {
//TreeSet构造方法在api是这样的:TreeSet(Comparator&? super E& comparator)
//上面自定义的比较器泛型是&Person&由于TreeSet接收的比较器的泛型是&? super E&这样的,也就是下限定
//也就是自定义的比较器MyComp只要是Person或Person的子类即可使用这个比较器
TreeSet&Student& t=new TreeSet&Student&(new MyComp()); //论证自定义的这个比较器可以用来比较Person的子类型的对象的
t.add(new Student(&Student-001&, 35));
t.add(new Student(&Student-002&, 24));
t.add(new Student(&Student-003&, 21));
t.add(new Student(&Student-004&, 24));
printList(t);//正吗这个方法可以打印装着实Student对象的泛型
TreeSet&Worker& t1=new TreeSet&Worker&(new MyComp());//论证自定义的这个比较器可以用来比较Person的子类型的对象的
t1.add(new Worker(&Worker-001&, 35));
t1.add(new Worker(&Worker-002&, 24));
t1.add(new Worker(&Worker-003&, 21));
t1.add(new Worker(&Worker-004&, 24));
printList(t1);//正名这方法可以打印装的是Worker类型的泛型
public static void printList(TreeSet&? extends Person& t){//&? extends Person&上限定,只要装的对象是Person的子类型既可以打印
Iterator&? extends Person& it= t.iterator();
while(it.hasNext()){
Person p=it.next();
System.out.println(p.name+&::&+p.age);
四:自定义泛型:
先参考下面:自定义泛型代码示例1
1.泛型类定义的泛型,在整个类中有效。如果被方法使用,
2.那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。
泛型方法:
3为了让不同方法可以操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。
4特殊之处:静态泛型
静态方法不可以访问类上定义的泛型。
如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
注意:泛型不可以使用类型的特有方法
自定义泛型代码示例1:
class Test {&
public static void main(String[] agrs) {
Demo&String& d=new Demo&String&();
d.show(&ds&);
d.print(34);
d.method(&静态泛型&);
class Demo&T&//这是一个泛型类
public &void show(T t)//这是一个就收泛型类型的参数的方法,接收类型随着泛型类走
System.out.println(&show:&+t);
public &Q& void print(Q q)//这是一个泛型方法,接收的参数由调用者决定,传的是什么就是什么
System.out.println(&print:&+q);
public &static &W& void method(W t)//这是一个静态泛型方法,接收的类型不可以跟随类泛型走,因为静态由先于对象存在
System.out.println(&method:&+t);
五:类型参数的类型推断
A:编译器判断范型方法的实际类型参数的过程称为类型推断,类型推断是相对于知觉推断的,其实现方法是一种非常复杂的过程。
B:根据调用泛型方法时实际传递的参数类型或返回值的类型来推断,具体规则如下:
& & & & 1.当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被应用了,那么根据调用方法时该处的实际应用类型来确定,这很容易凭着感觉推断出来,即直接根据调用方法时传递的参数类型或返回值来决定泛型参数的类型,例如:
& & & & & & & swap(new String[3],3,4)
& & & & & & & & & & & &——& & &static &E& voidswap(E[] a, int i, int j)
& & & & 2.当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型都对应同一种类型来确定,这很容易凭着感觉推断出来,例如:
& & & & & & & add(3,5)
& & & & & & & & & & &——& & static&T& T add(T a, T b)
& & & & &3.当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数中的最大交集类型,例如,下面语句实际对应的类型就是Number了,编译没问题,只是运行时出问题:
& & & & & & & &fill(new Integer[3],3.5f)
& & & & & & & & & & & ——& & &static&T& void fill(T[] a, T v)
& & & & &4.当某个类型变量在整个参数列表中的所有参数和返回值中的多处被应用了,如果调用方法时这多处的实际应用类型对应到了不同的类型,并且使用返回值,这时候优先考虑返回值的类型,例如,下面语句实际对应的类型就是Integer了,编译将报告错误,将变量x的类型改为float,对比eclipse报告的错误提示,接着再将变量x类型改为Number,则没有了错误:
& & & & & & & &intx =(3,3.5f)
& & & & & & & & & & & &——& & static&T& T add(T a, T b)
& & & & 5.参数类型的类型推断具有传递性,下面第一种情况推断实际参数类型为Object,编译没有问题,而第二种情况则根据参数化的Vector类实例将类型变量直接确定为String类型,编译将出现问题:
& & & & & & & &copy(newInteger[5],new String[5])
& & & & & & & & & & & & ——& & static&T& void copy(T[] a,T[] &b);
& & & & & & & &copy(newVector&String&(), new Integer[5])
& & & & & & & & & & & & & &——& & static&T& void copy(Collection&T& a , T[] b);
获取泛型的参数类型的代码示例:
public class Test {
public static void main(String[] agrs) throws Exception {
Test t=new Test();
Class clazz=t.getClass();
Method meth=clazz.getMethod(&method&,ArrayList.class);//获取方法的字节码
Type[] types=meth.getGenericParameterTypes();//获取方法的参数列表,参数列表的数量多个,所以返回的是数组
//System.out.println(types[0]);
//获取参数列表的具体某个参数的字节码;method方法的参数是:ArrayList&String&&
ParameterizedType type=(ParameterizedType)types[0];
//Type type=types[0];
//返回表示此类型实际类型参数的 Type对象的数组结果:class java.lang.String
System.out.println(type.getActualTypeArguments()[0]) ;
//返回 Type 对象,表示声明此类型的类或接口结果:class java.util.ArrayList
System.out.println(type.getRawType()) ;
public static &void method(ArrayList&String& arr){//用反射的办法获取泛型的类型
第四部分:加载器:
加载器:就是加载类的一个工具,也是也个java类。
作用:就是将cLass文件的二进制数据加载进内存
java虚拟机中可以安装多个类加载器,系统默认三个主要加载器:每个负责加载定位的类:BootStrap、ExtClassLoader、AppClassLoader。
2.加载器也是java类,因为其他是java类的加载器本身,也要被类加载加载,显然必须有一个类加载器不是java类,这正式:BootStrap类。
3.java虚拟机中的所有类加载器才用具有父子关系的树形结构进行组织,在示例化每个类装载器对象时,需要在为其指定一个父类加载器对象或者默认采用系统加载器为其父类加载
& 一:当Java虚拟机要加载一个类时,到底要用哪个类加载器加载呢?
& & & & &1.首先,当前线程的类加载器去加载线程中的第一个类。
& & & & &2.若A引用类B(继承或者使用了B),Java虚拟机将使用加载类的类加载器来加载类B。
& & & & &3.还可直接调用ClassLoader的LoaderClass()方法,来指定某个类加载器去加载某个类。
二:每个类加载器加载类时,又先委托给上级类加载器。
& & & &1. 类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类加载器去进行加载。当回退到最初的发起者类装载器时,如果它自己也不能完成类的装载,那就会抛出ClassNotFoundException异常。这时就不会再委托发起者加载器的子类去加载了,如果它还有子类的话。
& & & &2. 简单说,就是先由发起者将类一级级委托为BootStrap,从父级开始找,找到了直接返回,没找到再助剂让其子级找,直到发起者,再没找到就报异常。
三:委托机制的优点:
可以集中管理,不会产生多字节码重复的现象。
& & & & 可不可以自己写个类为:java.lang.System呢?
不可以,由于类加载器的委托机制,会先将System这个类一级级委托给最顶级的BootStrap,由于BootStrap在其指定的目录中加载的是rt.jar中的类,且其中有System这个类,此时就会被加载进内存,也就是说java定义好的类System类是不会被自己定义的类加载的
四:定义加载器:
加密步骤:
1.将要加密的class文件路径封装成File对象,并与字节读取流关联。
2.创建一个目的文件输出流对象,用于存储被加密后的文件,加密后的文件名要与被加密的文件名一样
3.读取一个字节数据,然后对读到的字节进行疑惑运算再写到目的class文件去。
4.将加密后的class文件覆盖原有的class文件即可
1.继承ClassLoader对象,复写findClass方法。
2:定义一个读取读取字节流并关联被覆盖的class目录的路径。
3.创建一个字节数组输出流,将读到的数据写进字节数组流里面去
4.调用字节数组流的toByteArray()方法将字节数组流转换成字节数组
5.调用继承过来的defineClass方法将字节数组转换成字节码,之后开始定义一个测试类对被加密的文件开始测试
加密加载器代码示例:
自定义加密加载器:工三个类:加载器类(具备解密和加密功能)类:MyClassLoader。被加载的类:Demo类。运行被加密的类:Test类
加密和解密类:
public class MyClassLoader extends ClassLoader{//加密和解密的类
public static void main(String[] args) throws IOException {
//将好的Class文件目录封装成对象
File f=new File(&E:\\workspace\\heima\\bin\\classLaoder&,&Demo.class&);
将File对象与流关联
InputStream r=new FileInputStream(f);
//创建一个加密class文件的文件对象,用于存放加密后的class文件
File de=new File(&E:\\workspace\\heima\\src\\classLib&,f.getName());
//将加密文件的File对象与流关联,
OutputStream w=new FileOutputStream(de);
jiaMi(r,w);
private static void jiaMi(InputStream target, OutputStream source) throws IOException {//加密方法
//byte [] buf=new byte[1024];
while(( (b=target.read())!=-1)){
source.write(b^255);//在写数据之前对数据进行移或运算,进行加密
source.flush();
source.close();
target.close();
public Class findClass() throws IOException{//解密方法
//将被加密的class文件封装成对象
File f=new File(&E:\\workspace\\heima\\bin\\classLaoder&,&Demo.class&);
//将文件对象与流光联
InputStream r=new FileInputStream(f);
//创建一个字节数组流对象,方便将读取到的字节码转换成字节数组
ByteArrayOutputStream w=new ByteArrayOutputStream();
jiaMi(r,w);//用加密的方法进行解密读取到字节数组流去
int len=w.toByteArray().
//return defineClass(w.toByteArray(), 0, len);
return defineClass(null, w.toByteArray(), 0, len);//反回字节数组
import java.io.IOE
public class Test {//测试类
public static void main(String[] args) throws &Exception{
MyClassLoader m=new MyClassLoader();
Class clazz=m.findClass();
Data data=(Data)clazz.newInstance();
System.out.println(data.toString());
System.out.println(clazz.getClassLoader());//打印结果是:classLaoder.MyClassLoader@6d06d69c
被加密的类
import java.sql.D
import javax.xml.crypto.D
public class Demo implements Data {//被加密的类
public String toString(){
return &自己加载的&;&
第五部分:代理
程序中的代理:
要为已经存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如异常处理,日子,计算方法运行时间,事务管理,等待该如何做呢?
编写一个目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法加上系统的功能代码。
如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类还是代理类,这样以后很容易切换,譬如:想要日志功能时就配置代理类,否则配置目标类,这样增加系统功能很容易以后运行一段时间之后,又想去掉系统也很容易
代理原理图3:
AOP切面图4:
使用代理技术正好可以解决这种问题,代理是实现AOP功能的核心和关键技术
要为系统中的各种接口的类增加代理功能,那将需要太多的代理,全部采用静态代理方式,将是一件非常麻烦的事情,写成百上千代理类,是很类的。
JVM可以在运行期动态生成出类的字节码,这种动态生成 的类往往被用作代理,即动态代理类。
JVM生成的动态代理类必须实现一个或多个接口,所以JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
代理类的各个方面中的中通常除了需要目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置上系统功能:
1.在调用目标的方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中
思考:让JVM创建动态类及其实例对象,需要给它提供哪些信息?
三个方面:
1.生成的类中哪些方法,通过让其实现那些接口的方式进行告知
2.产生的类字节码是怎样的,也是由我们提供,把我们的代码,写在一个约定好的接口对象的方法中,把对象传给它,它调用我的方法,即相当于插入了我们的代码,提供执行代码的对象,就是那个InvocationHandler对象,它是创建动态类的实例对象的构造方法时传递进去的,在上面的InvocationHandler对象invoke方法中加一点代码,就可以看到这些代码被调用了运行。
用Proxy.newInstance方法直接一步就创建出代理对象
创建动态代理对象实例代码:
import java.lang.reflect.InvocationH
import java.lang.reflect.M
import java.lang.reflect.P
import java.util.ArrayL
import java.util.C
public class Proxy_Text {
public static void main(String[] args) {//代理测试方法
ArrayList target=new ArrayList();
//注意:强转时,强转会目标的实现接口类型,不要强转会自己的类型
Collection collection=(Collection)getProxy(target, new MyAdvice());
collection.add(&张三&);
collection.add(&李四&);
collection.add(&王五&);
System.out.println(collection.size());
public static Object getProxy(Object target,Advice advice){//获取代理方法,接收要代理的目标target和增加的功能的建议:advice对象
//获取代理对象,该newProxyInstance()方法接收三个参数,
Proxy proxy=(Proxy) Proxy.newProxyInstance(
target.getClass().getClassLoader(),//传入目标的类加载器
target.getClass().getInterfaces(),//传如目标实现接口数组
new InvocationHandler() {//InvocationHandler匿名子类对象,复写InvocationHandler的invoke方法
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
advice.startTime(method);//调用提供出去的建议方法,统计开始时间
Object tar=method.invoke(target, args);
advice.endTime(method);//调用提供出去的建议方法,统计结束时间
interface Advice{//对外提供的将要增加的功能的建议接口
public void startTime(Method method);
public void endTime(Method method);
class MyAdvice implements Advice{//实现建议接口,用于增加代理的的功能,这是一个计算运行时间的功能
public void startTime(Method method) {
start=System.currentTimeMillis();
public void endTime(Method method) {
long end=System.currentTimeMillis();
System.out.println(method.getName()+&()方法运行了::: &+(end-start)+&:毫秒&);
AOP框架示例代码:
要求是:定义一个框架类,用于根据用户的配置文件获取Bean对象或者代理对象。如果是有xxx=proxy.proxyFaction代表的是需要的是代理,如果不是而是其它的类则返回Bean对象
同时对外提供一个接口,接口是用户需要代理时要增加的功能如:xxx.advice=proxy.MyAdvice。
下面定义了一个用于增加代理需要的功能接口Advice,一个实现类MyAdvice,用于测试时间的
一个:proxyFaction用于生产带来对象的类;一个是:BeanFaction用于获取代理或者Bean对象的类,其中包括主函数方法与测试,本该另外定义的。
对外提供的建议类:用于增加代理对象的具体功能
interface Advice{//对外提供的将要增加的功能的建议接口
public void startTime(Method method);
public void endTime(Method method);
实现建议接口,用于增加代理的的功能,这是一个计算运行时间的功能
class MyAdvice implements Advice{
public void startTime(Method method) {
start=System.currentTimeMillis();
public void endTime(Method method) {
long end=System.currentTimeMillis();
System.out.println(method.getName()+&()方法运行了::: &+(end-start)+&:毫秒&);
代理工厂类:用于生成代理对象的类
&class proxyFaction{
public Object getTarget() {
public void setTarget(Object target) {
this.target =
public Advice getAdvice() {
public void setAdvice(Advice advice) {
this.advice =
public Object getProxy(){
Object proxy=Proxy.newProxyInstance(target.getClass().getClassLoader(),&
target.getClass().getInterfaces(),&
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.startTime(method);
Object obj=method.invoke(target, args);
advice.endTime(method);
Bean工厂类,想要代理或者Bean对象由用户去在配置文件配置
import java.io.IOE
import java.io.InputS
import java.lang.reflect.InvocationH
import java.lang.reflect.M
import java.lang.reflect.P
import java.util.C
import java.util.P
public class BeanFaction {
private InputS
public BeanFaction(InputStream ips) {
pro=new Properties();
public static void main(String[] agrs) {//主程序注意用于测试用而已,为了方便就写进一个类了
//创建对象将配置文件与流关联对流对象初始化。
BeanFaction f=new BeanFaction(BeanFaction.class.getResourceAsStream(&config.propertie&));
Collection c=(Collection)f.getBean();
System.out.println(c.add(&ds&));
public Object getBean() {//获取bean对象或者代理的方法,根据配置文件而决定
Object bean=
pro.load(ips);//将关联配置文件的流对加载进集合中
String className=pro.getProperty(&xxx&);//获取文件名
Class clazz=Class.forName(className);//根据文件名获取字节码
bean=clazz.newInstance();//根据字节码创建实例对象
if (bean instanceof proxyFaction) {//如果实例的对象,符合proxyFaction的则是需要获取代理的。
proxyFaction proxyFaction=(proxyFaction)
//获取配置文件的需要代理的目标对象
Object target=Class.forName(pro.getProperty(&xxx.target&)).newInstance();
//代理需要增加的功能对象,这个功能是提供出去的一个接口,由用户去扩展实现之后传回来
Advice advice=(Advice)Class.forName(pro.getProperty(&xxx.advice&)).newInstance();
proxyFaction.setAdvice(advice);//将功能增加进去
proxyFaction.setTarget(target);//加代理目标设置进去
return proxyFaction.getProxy();//反会代理对象
} catch (Exception e) {
e.printStackTrace();
配置文件内容如:
#xxx=java.util.ArrayList
xxx=proxy.proxyFaction
xxx.advice=proxy.MyAdvice
xxx.target=java.util.ArrayList
、期待与您交流! -------
java高新技术课程:
本章内容:
一:jkd1.5的新特性枚举
第一部分:枚举:
一:JDK1.5的新特性 :枚举
为什么需要枚举?
首先我们思考:如果是星期几,那么用一个变量来定义,那么怎么定义呢,也许有的认为周一是一个星期的第一天,也许有的是周日是一个星期的第一天。由于答案的不一,也就是说变量的多样性,那么为了规范,我们可以通过枚举类来实现这目标,使若干个变量的值,固定在一个值,如果不是我规定的值,那么就会导致你编译不通过,报错。
1.枚举其实就是要强制规定类型变量的值。枚举的元素指向的是本类类型的一个匿名子类对象,枚举元素就是一个常量
2.枚举就是让大量的if else语句转成一个独立的抽象的类。
用普通类的方法来推理枚举:
&  首先:将构造函数私有化,其次向外提供公共的访问方法就是将,本类类型的类变量,静态私有化。本来是可以用若干个if else来完成的现在用若干个匿名内部类来完成这工能
&abstract class &Week{
//私有化变量
private Week() {
//静态提供访问方法,并保证变量值的固定性
public final static Week sun=new Week(){
public Week getNextDate() {
public final static Week mon=new Week(){
Week getNextDate() {
abstract Week getNextDate() ;
public String toString (){
return this==mon? &sun&:&mon&;
通过上面的推理,下面开始定义一个枚举类,用到关键字enum
&public class Test {//枚举测试类
public static void main(String[] agrs) &{
System.out.println(Week.SUN);//结果是SUN
System.out.println(Week.SUN.TUN);//结果是:TUN
&public enum Week{//这就是一个简单的枚举;
SUN,MON,TUN,WED,THI,FRI,STA
应用总结:
1.枚举类的元素以外其他东西,如方法或者构造函数,必须在元素的后面,如果放在元素的前面的话会报错。
2.枚的构造方法必须是private的
3.如果想调用枚举类的有参构造方法时,可以在元素后面加个小括号,并传入对应的参数
4.其实枚举类的元素就是一个公有、静态的本类类型常量量,指向的是本类类型的匿名子类对象
5.如果枚举类有抽象方法,那么其元素必须要实现其抽象方法,
6.枚举类其实也就相当于一个抽象类
7.如果枚举中只有一个成员那么可以看作成是单例的实现方式,单例还要new对象,枚举省了new对象和加修饰符的麻烦,就写以一个常量名就可以的到了本来对象
注意:Object中的方法finalize(),枚举类不能有 finalize 方法。
Enum类的方法:
static &T extends Enum&T&& T &valueOf(Class&T& enumType, String name)&
& & & & & 返回带指定名称的指定枚举类型的枚举常量。&
int ordinal()&
& & & & & 返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。&
Class&E& getDeclaringClass()&
& & & & 返回与此枚举常量的枚举类型相对应的 Class 对象。&
下面是交通灯枚举的定义示例代码:
enum Traffic{//这是一个交通等枚举类定义了:有三个元素RED GREEN YELLOW ;一个成员变量time,和一个抽象方法和一个又参的构造方法
RED(30) {&
public Traffic nexLemp() {
return GREEN;
GREEN(30) {&
public Traffic nexLemp() {
return GREEN;
YELLOW(10) {
public Traffic nexLemp() {
return RED;
private Traffic(int time){
this.time=
public abstract Traffic nexLemp();
第二部分:反射:
反射的基石——&Class类
java程序中的各个java类就属于同一类事物,描述java类的就是class类
一个类加载在内存中,占用一片存储类空间,这个空间里面的内容就是类的字节码,不同的类的字节码是不同的,所以它们在内存中的内容也是不同的,这一个个的空间的字节码可分别用一个个的对象来表示,这些对象显然具有相同的类型,这个类型就是Class类型。那么如何来得到这个类型的对象呢?可以通过Class类
获取字节码的方法:
如:获取类:Person的字节码:
1. 类名点getClass()如:Class clazz=Person.
2.Class类中的方法forName():如:Class clazz=Class.forName();
3.对象名.class如:Class clazz=new Person().
注:不管你用哪种方法搞出来的字节码,同一个类型字节码相同,也就是说字节码是唯一的
那么什么是反射呢?
由于每个java类中的各个成分都可以通过Class类来描述,每一个类都有对应不同的字节码,那么反射就是通过类的字节码来获取到类的各个成分,通过对类的解刨,就可以操作其内部的功能和属性。也就是说反射就是通过字节码来对类的各种成分解刨、获取、或者操作,这就是反射。
通过反射的手段,可以得到自解码的各个成分,那么当拿到了各个成分之后,该怎么来操作其各个成分呢?
java类通常包括以下行为、属性或表现形式:
方法、字段、构造方法、参数、包、实现接口等信息,在java中也用了对应的类进行对这些信息进行具体的描述,如字段:Field;方法:Method;构造方法:C参数:Type等类对其方法的描述,那么就可以调用描述这种行为和属性的方法的对应描述的类中的方法即可操作字节码的行为和属性。具体操作看下面示例代码:
Class类介绍:
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。&
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。&
isPrimitive()//判定指定的 Class 对象是否表示一个基本类型。有九种预定义的 Class 对象,表示八个基本类型和 void。这些类对象由 Java 虚拟机创建,
九个基本类型字节码:Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE, Void.TYPE
如:int.class==Integert.TYPE//结果是true 。int.class==Integer.class//结果是false。
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。&
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。&
以下示例使用 Class 对象来显示对象的类名:&
& & &void printClassName(Object obj) {
& & & & &System.out.println(&The class of & + obj + & is & + obj.getClass().getName())
反射方法:
Method getDeclaredMethod(String name, Class&?&... parameterTypes)&
& & & & & 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。&
& Method[] getDeclaredMethods()&
& & & & & 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。&
Method getMethod(String name, Class&?&... parameterTypes)&
& & & & & 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。&
& Method[] getMethods()&
& & & & & 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法&
Constructor&T& getDeclaredConstructor(Class&?&... parameterTypes)&
& & & & &返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。&
Constructor&?&[] getDeclaredConstructors()&
& & & & & 返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
Constructor&T& getConstructor(Class&?&... parameterTypes)&
& & & & & 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。&
& Constructor&?&[] getConstructors()&
& & & & &返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。&
Field getDeclaredField(String name)&
& & & & & 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。&
Field[] getDeclaredFields()&
& & & & &返回 Field 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段。&
Field getField(String name)&
& & & & &返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。&
& Field[] getFields()&
& & & & & 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段&
& T newInstance()&
& & & & & 创建此 Class 对象所表示的类的一个新实例。&
InputStream getResourceAsStream(String name)&
& & & & &查找具有给定名称的资源。&
ClassLoader getClassLoader()&
& & & & & 返回该类的类加载器。&
Class&?& getComponentType()&
& & & & &返回表示数组组件类型的 Class。&
U& Class&? extends U& &asSubclass(Class&U& clazz)&
& & & & &强制转换该 Class 对象,以表示指定的 class 对象所表示的类的一个子类。
static Class&?& forName(String className)&
& & & & & 返回与带有给定字符串名的类或接口相关联的 Class 对象。&
static Class&?& forName(String name, boolean initialize, ClassLoader loader)&
& & & & & 使用给定的类加载器,返回与带有给定字符串名的类或接口相关联的 Class 对象。
Class&? super T& getSuperclass()&
& & & & &返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的超类的 Class。 &
boolean isArray()&
& & & & &判定此 Class 对象是否表示一个数组类。&
boolean isInstance(Object obj)&
& & & & & 判定指定的 Object 是否与此 Class 所表示的对象赋值兼容。&
& boolean isInterface()&
& & & & &判定指定的 Class 对象是否表示一个接口类型。&
Class&?&[] getInterfaces()&
& & & & & 确定此对象所表示的类或接口实现的接口。&
一 :反射构造方法:
1.通过类名.clas的到类自字节码。
2.同过字节码得到指定的构造方法,如果是有参数的构造方法要在构造传入参数的字节码对象。
3通过调用Constructor类中的newInstance方法可以创建实例对象,注意这时接收的参数是参数字节码类型的实际参数。返回的是Object类型的,可以将强转会实际类型
类:Constructor
Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。 Constructor 允许在将实参与带有底层构造方法的形参的 newInstance() 匹配时进行扩展转换,但是如果发生收缩转换,则抛出 IllegalArgumentException。&
T newInstance(Object... initargs) 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。
代码实例:
&public class Test {
public static void Primitive(){//判断是否是基本数据类型
//判定指定的 Class 对象是否表示一个基本类型。有九种预定义的 Class 对象,表示八个基本类型和 void。这些类对象由 Java 虚拟机创建
System.out.println(int.class.isPrimitive());
System.out.println(Integer.TYPE.isPrimitive());//结果是true,Integer.TYPE==int.class
System.out.println(Void.TYPE.isPrimitive());//结果是true,Void.TYPE==void.class
public static void Constructor() throws Exception{//构造方法的反射
//构造方法反射:
//1.通过获得clas字节码。2.同过字节码得到指定的构造方法,如果是有参数的构造方法要在构造传入参数的字节码对象。
//3通过调用Constructor类中的newInstance方法可以创建实例对象,注意这时接收的参数是参数字节码类型的实际参数。
//返回的是Object类型的,可以将强转会实际类型
Constructor con=String.class.getConstructor(String.class);
String str=(String)con.newInstance(&abcd&);
System.out.println(str.charAt(2));//结果是c
二:字段的反射:
类:Field:
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。 Array 允许在执行 get 或 set 访问操作期间进行扩展转换,但如果将发生收缩转换,则抛出一个 IllegalArgumentException
常用的方法:
Object get(Object obj)&
& & & & & 返回指定对象上此 Field 表示的字段的值。&
void set(Object obj, Object value)&
& & & & & 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。&
Class&?& getType()&
& & & & & 返回一个 Class 对象,它标识了此 Field 对象所表示字段的声明类型。&
int getInt(Object obj)//获取对应的是int的值,
long getLong(Object obj)&
& getShort(Object obj)
getChar(Object obj)
getBoolean(Object obj)
getDouble(Object obj);
setChar(Object obj, char value)
setInt(Object obj, int value)
public class Test {
public String str=&abcdb&;
public String toString(){
public static void main(String[] agrs) throws Exception &{
public static void field() throws Exception{//字段的反射
//getField()获取到的只是public的字段的字节码否则会报错
//getDeclaredField()获取到的所有的字段的字节码包括私有,这时只可以访问非私有的字段
//当字段私有后,想访问还需要调用setAccessible(true)设置为true
Test t=new Test(3,6);
Field field=t.getClass().getDeclaredField(&y&);
field.setAccessible(true);//私有的字段要对这个参数设置为true,
System.out.println(field.get(t));//结果是Integer类型的:6
System.out.println(field.getInt(t));//结果是int类型的:6
//练习:要求将所有的字符串字段的包含有b的设置改成c
public static void field1() throws &Exception{
Test t=new Test(2,3);
System.out.println(&设置前的字符串:&+t);
Class cazz=t.getClass();
Field[] field=cazz.getDeclaredFields();//获取所有的的字段的字节码
for(Field f:field){
if (f.getType()==String.class) {//类 型的字解码就一份,所有用==比较
String str=(String)f.get(t);//得到了实际的字段
String newStr=str.replace('b', 'c');//对字段开始替换,得到了一个新的字符串
f.set(t,newStr);//将新的字符串设置到字段取
System.out.println(&设置后的字符串:&+t);
三:反射方法:
类:Method
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。 Method 允许在匹配要调用的实参与底层方法的形参时进行扩展转换;但如果要进行收缩转换,则会抛出 IllegalArgumentException。&
Type[] getGenericParameterTypes()&
& & & & &按照声明顺序返回 Type 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型的。&
Type getGenericReturnType()&
& & & & & 返回表示由此 Method 对象所表示方法的正式返回类型的 Type 对象。&
Class&?&[] getParameterTypes()&
& & & & &按照声明顺序返回 Class 对象的数组,这些对象描述了此 Method 对象所表示的方法的形参类型。&
Class&?& getReturnType()&
& & & & & 返回一个 Class 对象,该对象描述了此 Method 对象所表示的方法的正式返回类型。&
Object invoke(Object obj, Object... args)&
& & & & &对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。&
String toGenericString()&
& & & & & 返回描述此 Method 的字符串,包括类型参数。&
Class类反射方法的方法:
Method getMethod(String name, Class&?&... parameterTypes)&
& & & & &返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。&
& Method[] getMethods()&
& & & & & 返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法。&
Method getDeclaredMethod(String name, Class&?&... parameterTypes)&
& & & & & 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。&
& Method[] getDeclaredMethods()&
& & & & & 返回 Method 对象的一个数组,这些对象反映此 Class 对象表示的类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。&
注意:当反射的方法的参数是数组时注意,比如反射main方法,接收的参数是数组,如果用反射的方法,通过调用invoke方法如何传递参数呢?按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素对应一个参数,当把一个字符串数组作为参数传递给invoke方法时,javac会到底按照哪种语法进行处理呢?jdk1.5肯定要兼容jdk1.4的语法,会按jdk1.4的语法进行处理,即把数组打散成为若干个单独的参数。所以,在给main方法传递参数时,不能使用代码mainMethod.invoke(null,new String[]{“xxx”}),javac只把它当作jdk1.4的语法进行理解,而不把它当作jdk1.5的语法解释,因此会出现参数类型不对的问题。
解决办法:
& & & & & & & & & &mainMethod.invoke(null,new Object[]{new String[]{&xxx&}});
& & & & & & & & & &mainMethod.invoke(null,(Object)new String[]{&xxx&});编译器会作特殊处理,编译时不把参数当作数组看待,也就不会把数组打散成若干个参数了。
&public class Test {
public int getX(){
public void setX(int x){
public static void main(String[] agrs) throws Exception &{
public static void method() throws Exception{
Class clazz=Class.forName(&heima.Test&);
Test t=(Test) clazz.newInstance();
Method method=clazz.getMethod(&setX&, int.class);
method.invoke(t, 88);//通过对反射的方法对方法的调用
System.out.println(t.x);//打印结果是88
//反射main方法,main方法接收的参数是字符串数组,那么在反射的时候参数接收的也是可变参数字节码,当传入的是数组字节码时,
//实际调用的时候传入的是实际参数,要对数组在进行包装在一个数组内,否则会被拆包成多个参数
Class clazz1=Class.forName(&heima.Server_Test&);//heima.Server_Test是一个类,执行的是这个类的main方法
Method main=clazz1.getMethod(&main&, new String[]{&22&,&32&}.getClass());
main.invoke(null,new Object[]{new String[]{&22&,&32&}});
四:数组的方射:
类:Array&
Array 类提供了动态创建和访问 Java 数组的方法。&
Array 允许在执行 get 或 set 操作期间进行扩展转换,但如果发生收缩转换,则抛出 IllegalArgumentException。&
static Object get(Object array, int index)&
& & & & &返回指定数组对象中索引组件的值。
getLength(Object array)&
& & & & & 以 int 形式返回指定数组对象的长度。
static void set(Object array, int index, Object value)&
& & & & &将指定数组对象中索引组件的值设置为指定的新值。 &
static void setInt(Object array, int index, int i)&
& & & & & 将指定数组对象中索引组件的值设置为指定的 int 值&
static int getInt(Object array, int index)&
& & & & & & &以 int 形式返回指定数组对象中索引组件的值。&
其它的基本数据类型的set和get方法同理......
1.具有相同维数和元素类型的数组属于同一个类型,即具有相同的Class的实例对象
2,代表数组class实例对象的方法的getSuperClass()方法返回的父类为Objectl类对应的Class .
3.基本类型的一维数组可以被当作Object类型使用,不能当作Object[]类型使用,非基本类型的一维数组,既可以当做Object类型使用,又可以当做Object[]类型使用。
4.Arrays.asList()方法处理int[]和String[]时的差异
当是int[]数组时会把就会按照1.5的处理,当是String[]会按照1.4的语法处理,由于1.4以前接收的是Object数组,而1.5之后是接收的是可变参数,当是基本数据类型数组时,就会根据1.5的语法来编译执行,把整个数组当一个参数来处理,而当是Object类型数组时,由于新版本要兼容老版本,当符合1.4语法就会按1.4的来执行。
5.怎么样得到数组中的元素的类型?
没有办法得到数组中类型,只可以的到数组中的某个元素的类型。
&public class Test {
public static void main(String[] agrs) throws Exception &{
arr(new int[]{32,43});
public static void arr1(){
int [] arr1 = new int[]{2,3};
int [] arr2 = new int[4];
int[][] a3 = new int[2][3];
String [] a4 = new String[]{&a&,&b&,&c&};
// System.out.println(arr1.getClass() == arr2.getClass());//结果true
//System.out.println(arr1.getClass().getName());//结果:[I
//System.out.println(arr2.getClass().getName());//结果:[I
//System.out.println(arr1.getClass().getSuperclass().getName());//结果:java.lang.Object
//System.out.println(a4.getClass().getSuperclass().getName());//结果:java.lang.Object
Object aObj1 = arr1;
Object aObj2 = a4;
//Object[] aObj3 = a1;
Object[] aObj4 = a3;
Object[] aObj5 = a4;
// System.out.println(arr1);//结果:[I@15db9742
// System.out.println(a4);//[Ljava.lang.S@6d06d69c
System.out.println(Arrays.asList(arr1));//[[I@15db9742]如果是基本数据类型的话就把整个数组当作一个元素
System.out.println(Arrays.asList(a4)); //[a, b, c]如果是Object类型的话就会把数组d元素当作元素
public static void arr(Object obj){
Class clazz=obj.getClass();
if (clazz.isArray()) {
int len=Array.getLength(obj);
for(int x=0;x&x++){
System.out.println(Array.get(obj, x));
System.out.println(obj);
五:hashCode()的分析:
在HashSet集合中如果想查找一个集合中是否包含某个对象,大概的程序代码是怎么样写呢?通常是取出每个元素与要查找的对象进行比较,当发现某个元素与要查询的对象的equals方法比较的结果相等时,则停止继续查找并返回肯定的信息,否则返回否定的信息,假设要有一万多个元素,并且没有所要查找的,那么就意味着程序要取出一万个来一一比较才可以得到结论。后来有人发明了一种算法,就是哈希算法来提高从集合查找的速度。这种方式就是将集合分成若干个区域,每个对象可以计算出来一个哈希值,可以将哈希值分组,每组分别对应某个存储区域,就根据一个对象的哈希姆就可以确定哈希对象存储在那个区域。
HashSet就是采用哈希值算法来存储元素的一个集合。它内部采用的对某个数字n进行取余的方式对哈希码进行分组和划分对象的存储区域,在Object定义了hashCode方法来返回每个对象的哈希值,当HashSet集合查找某个对象时java系统首先调用对象的hashcode()方法来获得哈希值然后根据哈希值来查找对应的区域,然后取出该存储区域在内存中的元素与该对象的equals方法比较,这样就不用遍历集合的所有的元素就可以得到结果了。可见HashSet集合具有很好的对象检索性能,但是hashSet集合存储对象效率相对较低,因为hashSet集合增加每个对象的时候都要对对象的哈希值和根据这个哈希码确定对象在集合的存放的位置。
为了保证一个类的实例对象在HashSet集合正常存储,要求这个类的两个示例对象用equals方法比较的结果相等时,他们的哈希码也必须相等,也就是说,如果equals的结果为true,那么hashCode的结果也要为true。
如果一个类的hashCode方法没有遵循上述要求。那么当这个类的两个对象用equals方法比较的结果相等时,他们本来应该无法同时存储进Set的集合的,但是如果将他们存进去的比较结果相等时,由于他们的hashCode()方法的返回值不同,第二个对象首先要对哈希码计算,可能会被放进去与第一个对象不同的区域中,这样,它不可能与第一个对象进行equals方法比较,也就可能被存进hashSet集合中了,Object类的hashCode()方法不能满足对象存入到HashSet集合中 的要求。因为他的返回值是通过对象内存地址来推算出来的,同一个对象在程序运行期间的任何时候返回的的哈希值都是始终不变的,所以只要是两个不同示例对象,即使他们的equals相等他们的默认的hashCode方法的返回值是不同的。
只要类的实例对象要被采用哈希算法进行存储检索时,这个类就需要覆盖hashCode方法,即时程序暂时没有用到hashCode方法,但是为了提供一个hashCode方法,也不会有什么不好,没准以后什么时又用到了这个方法了,所以要求hashCode方法和equals方法同时覆盖。
当一个对象存储进HashSet集合中以后,就不能修改这个对象的那些参与计算哈希值的字段了,否则对象修改后的哈希值就会与最初存进去HashSet集合中的时候的哈希值不一样,这样的情况下,即使contains方法是用的该对象的当前引用作为参数去HashSet集合中检索对象时,也将返回找不到对象的结果,也会导致了无法从HashSet集合中单独删除当前对象,从而导致了内存泄漏。
内存泄漏其实就是本来对象在内存中不在使用了,应该在内存中释放内存空间的,但并没有被释放,还继续在内存中存在,就像集合中的元素,本来删除了就不应该再在集合中,但是删除后还在集合中,这样的日积月累的下去,内存的空间就会导致了没有了内存空间,导致了内存溢出,这就是说内存泄漏了
import java.util.HashS
public class HashCode {
public static void main(String[] args) {
//HashSet h=new HashSet();
HashSet h=new HashSet();
Person p1=new Person(&李四&,22);
Person p2=new Person(&王五&,24);
Person p3=new Person(&张三&,23);
Person p4=new Person(&张三&,23);
h.add(p1);
h.add(p2);
h.add(p3);
h.add(p4);
p1.age=34;
h.remove(p1);//当集合的元素被修改了之后,在调用集合的删除和修改的方法操作数据时,会导致内存泄漏
System.out.println(h.contains(p1));//false
System.out.println(h.size());
class Person{
Person(String name,int age){
this.name=
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result +
result = prime * result + ((name == null) ? 0 : name.hashCode());
public boolean equals(Object obj) {
if (this == obj)
if (obj == null)
if (getClass() != obj.getClass())
Person other = (Person)
if (age != other.age)
if (name == null) {
if (other.name != null)
} else if (!name.equals(other.name))
六:反射的作用---&实现框架的功能:
框架与框架要解决的核心问题:
1如:我做房子卖给用户,由用户来装门和空调等。我做的房子就是一个框架,用户需要使用我的框架,把门窗装上去我提供的框架中,框架与工具类有区别,工具类被用户的类调用,而框架则是调用用户提供的类
框架要解决的核心问题?
1.我在写框架的时候,也许你还在上小学,还不会写程序,我写的框架程序怎么样能调用到你以后的类呢?
2.因为是在写这个程序时无法知道要被调用的类名,所以,在程序中无法直接new某个类的实例对象的,而需要反射的方式来做。
类加载器的资源文件配置问题:
通常配置文件放在哪里呢?
可以放在class目录下,通过类加载器来将配置文件一同加载进内存
1.通过类加载器:
把配置文件放在class目录下,通过执行程序类的字节码,通过getClassLoader()方法获得类的加载器,在通过getResourceAsStream方法得到关联资源文件的读取字节流,在通过Properties对象的load()方法将配置文件内容加载进集合,这时就完成了对文件的加载和读取了。
2.其实在Class类也提供了加载资源的方法,就是通过getResourceAsStream()方法来完成获取读取流对像,文件名也是放在class目录下,使用时直接写文件名即可,如果放在在class目录下的包用/隔开,这种方法其实也底层也是通过类加载器来完成的,
具体操作看下面示例代码:
public class HashCode {
public static void main(String[] args)throws Exception{
//第一中相对路径的做法,一般不是那么干的,一定要记住用完整的路径,但完整的路径不是硬编码,而是通过getRealPath()运算出来的
//InputStream ip1=new FileInputStream(&config.properties&);
Properties p=new Properties();
//第二种通过加载器的方法,就是把配置文件和class文件放在同一个包下,使加载class文件时将配置文件一起加载。注意:前面不要加/
// InputStream ip2 = HashCode.class.getClassLoader().getResourceAsStream(&config.properties&);
//Class类提供的方法,把文件放在class目录下,代表的是当前class目录下的目录,如果当前在class下的包用/来隔开
//InputStream ip3 = HashCode.class.getResourceAsStream(&/resources/config.properties&);//把配置文件放在class目录下的resource包
InputStream ip3 = HashCode.class.getResourceAsStream(&config.properties&);//把配置文件放在class path目录下
p.load(ip3);
ip3.close();
String className=p.getProperty(&className&);
Collection collection=(Collection)Class.forName(className).newInstance();
Person p1=new Person(&李四&,22);
Person p2=new Person(&王五&,24);
Person p3=new Person(&张三&,23);
Person p4=new Person(&张三&,23);
collection.add(p1);
collection.add(p2);
collection.add(p3);
collection.add(p4);
System.out.println(collection.size());
、期待与您交流! -------
第二十五:正则表达式:
正则表达式:符合一定规则的表达式。
作用:用于专门操作字符串。
特点:用于一些特定的符号来表示一些代码操作。这样就简化书写。
所以学习正则表达式,就是在学习一些特殊符号的使用。
好处:可以简化对字符串的复杂操作。
弊端:符号定义越多,正则越长,阅读性越差。
具体操作功能:
1.匹配:String &matches方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
2.切割:String split();
3.替换:String replaceAll(regex,str);如果regex中有定义组,可以在第二参数中通过$符号获取正则表达式中的已有的组。
[abc] a、b 或 c(简单类)&
[^abc] 任何字符,除了 a、b 或 c(否定)&
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)&
[a-d[m-p]] a 到 d 或 m 到 p:[a-dm-p](并集)&
[a-z&&[def]] d、e 或 f(交集)&
[a-z&&[^bc]] a 到 z,除了 b 和 c:[ad-z](减去)&
[a-z&&[^m-p]] a 到 z,而非 m 到 p:[a-lq-z](减去)
预定义字符类&
. 任何字符(与行结束符可能匹配也可能不匹配)&
\d 数字:[0-9]&
\D 非数字: [^0-9]&
\s 空白字符:[ \t\n\x0B\f\r]&
\S 非空白字符:[^\s]&
\w 单词字符:[a-zA-Z_0-9]&
\W 非单词字符:[^\w]&
& 注意:在java的\要转义
Greedy 数量词&
X? X,一次或一次也没有&
X* X,零次或多次&
X+ X,一次或多次&
X{n} X,恰好 n 次&
X{n,} X,至少 n 次&
X{n,m} X,至少 n 次,但是不超过 m 次&
组的捕获:\n 如:切割叠词:&(.)\1+&;也就是将规则用()封装成组,用\n来捕获,
$:在规则外面获取组:如rePlaceAll(&(.)\1+&,$1);//将叠词替换成一个词
捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:&
1 & & ((A)(B(C)))&
3 & & (B(C))&
4 & & (C)&
组零始终代表整个表达
边界匹配器&
^ 行的开头&
$ 行的结尾&
\b 单词边界&
\B 非单词边界&
\A 输入的开头&
\G 上一个匹配的结尾&
\Z 输入的结尾,仅用于最后的结束符(如果有的话)&
\z 输入的结尾&
切割一个或者多个多个空格:& +&;
切割点:&\\.&;
切割叠词:&(.)\1+&;
正则表达式的第四个功能获取
操作步骤:
1.将正则表达式封装成对象。
2.让正则对象和要操作的字符串相关联。
3.关联后,获取正则匹配引擎。
4.通过引擎对符合规则的子串进行操作,比如取出。
正则使用功能选择思路:
思路方式:
1.如果只想知道该字符是否对是错,使用匹配。
2.想要将已有的字符串变成另一个字符串,替换。
3.想要按照自定的方式将字符串变成多个字符串。切割。获取规则以外的子串。
4.想要拿到符合需求的字符串子串,获取。获取符合规则的子串。
正则表达式代码示例:
import java.util.regex.M
import java.util.regex.P
public class regex {
public static void main(String[] args) {
matches(&&);//对qq号码校验;要求:5~15 &0不能开头,只能是数字;匹配:regex=&[1-9]\\d{4,14}&
matches1(&&);//对手机号码校要求:是1开头,第二位3、5、8;验匹配:regex=&[1][358]\\d{9}&;
split(&ldks &dksl &agfbn lf &);//按空格切割:结果是数组长度:4
split1(&holle.java.demo..java..&);//按点切:匹配:regex=&\\.+&;结果是数组长度:4
replaceDemo(&dskl3232323klm34l;m433334;;mmh33333&);//要求:将字符串中的数字替换成#:匹配:regex=&\\d{5,}&;结果是:dskl#klm34l;m#;;mmh#
replaceDemo1(&aabbkkkcknkkkww&); //要求:将叠词替换成@:匹配:regex=&(.)\\1+&;结果是:@@@ckn@@
replaceDemo2(&aadddbbbkmdsss&);//要求:将叠词替换成一个;匹配:regex=&(.)\\1+&;方法使用:str.replaceAll(regex, &$1&)
getPattern();//正则获取
public static &void getPattern(){//
//要求:获取三个连续字母的单词
String str=&ming tian &jiu yao fang jia le&;//结果是:jiu yao jia&
String regex=&\\b\\w{3}\\b&;
Pattern pile(regex);//将规则与正则对象关联,封装成正则对象
Matcher m=p.matcher(str);//通过正则对象获得匹配器,并将将要匹配的字符串传给匹配器
while(m.find()){//通过find()方法对字符串查找匹配,并根据匹配查找的结果,如果为true,在通过group()方法来获取 //匹配到的字符串
System.out.print(m.group()+& &);
public static void replaceDemo(String str){
//要求:将字符串中的数字替换成#
String regex=&\\d{5,}&;
System.out.println(str.replaceAll(regex, &#&)); //结果是:dskl#klm34l;m#;;mmh#
public static void replaceDemo1(String str){
//要求:将叠词替换成@
String regex=&(.)\\1+&;
System.out.println(str.replaceAll(regex, &@&));&
public static void replaceDemo2(String str){
//要求:将叠词替换成一个
String regex=&(.)\\1+&;
System.out.println(str.replaceAll(regex, &$1&));&
public static void split(String str){
//要求:按照一个或者多个空格来进行切割
String regex=& +&;
String [] arr=str.split(regex);
System.out.println(&空格切:&+arr.length);//结果是4
public static void split1(String str){
//要求:按照一个或者多个.来进行切割
String regex=&\\.+&;
String [] arr=str.split(regex);
System.out.println(&点切:&+arr.length);//结果是4
public static void matches(String str){
// 对QQ号码进行校验
// 要求:5~15 &0不能开头,只能是数字
String regex=&[1-9]\\d{4,14}&;
if (str.matches(regex)) {
System.out.println(&qq号码正确&);
System.out.println(&qq号码错误&);
public static void matches1(String str){
// 手机号段只有 13xxx 15xxx 18xxxx
String regex=&[1][358]\\d{9}&;
if (str.matches(regex)) {
System.out.println(&手机号码正确&);
System.out.println(&手机号码错误&);
练习:油箱校验、ip地址排序、去除重复的字,只保留:我要学编程
public class regex {
public static void main(String[] args) {
ipSort();//ip地址排序
show();//去除重复的字,只保留:我要学编程
mail();//油箱校验
public static void mail(){//油箱校验
String str=&&;
String regex=&\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}&;
System.out.println(str.matches(regex));
public static void show(){//去除重复的字,只保留:我要学编程
String str = &我我...我我...我要..要要...要要...学学学....学学...编编编...编程..程.程程...程...程&;
str=str.replaceAll(&\\.&,&&);//去掉点
System.out.println(str);
System.out.println(str.replaceAll(&(.)\\1+&, &$1&));//将叠词字符去除捕获一个
public static void &ipSort(){//ip排序
String ip = &192.68.1.254 102.49.23.013 10.10.10.10 2.2.2.2 8.109.90.30&;
ip=ip.replaceAll(&(\\d+)&,&00$1&);//第一步不两个前面0
ip=ip.replaceAll(&0*(\\d{3})&,&$1&);//第二部:保留后三位,
String[] ip2=ip.split(& &);//将截取没 一个ip
TreeSet&String& t=new TreeSet&String&();//建一个容器,存ip并对ip排序
for(String x:ip2){
for(String ip3:t){
System.out.println(&排序后:&+ip3.replaceAll(&0*(\\d+)&,&$1&));//将派好序的ip去除前面补的 0
、期待与您交流! -------
第23天:网络编程:
一:了解网络通信的原理:网络模型:OSI参考模型、TCP/IP参考模型
二:TCP通信和UDP通信
三:自定义浏览器和域名解析涉URL和URLConnection对象
注:其中包括一些模拟登陆、并发上传图片文件、等练习。
第一部分:对网络通信原理了解:
一:网络模型:
1.OSI参考模型
2.TCP/IP参考模型
网络通讯要素:
3.传输协议
本机回环地址:127.0.0.1
一般来说软件开发就是是在传输层和网际层混的;传输层常见的是:UDP和TCP等,网际层常见的协议:IP。应用层常见的:FTP和HTTP协议。
二:IP地址
& & & & 1.IP地址它是网络中的设备标识
& & & & 2.不易记忆,可用主机名表示,两者存在映射关系
& & & & 3.本机回环地址:127.0.0.1,主机名为:localhost。
注:广播地址:192.168.1.255
在java描述ip地址的对象是:java.net.InetAddress
方法:static InetAddress getByName(String host)&
在给定主机名的情况下确定主机的 IP 地址。
String getHostAddress()&
& & & & & 返回 IP 地址字符串(以文本表现形式)。&
String getHostName()&
& & & & &获取此 IP 地址的主机名&
& & & & & 在给定主机名的情况下确定主机的 IP 地址。&
三:端口号:
有效端口:0-66535,其中:0-1024是系统使用的保留端口
四:常见协议:
协议特点:
& & & & &1.面向无连接,即将数据及源和目的封装成}

我要回帖

更多关于 哈希查找时间复杂度 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信