精华内容
下载资源
问答
  • 方法1、将所有文件内容一次读取到程序之中,然后一次输出;这样话就需要开启一个跟文件一样大小数据用于临时保存这些数据,但是当文件过大时候呢?程序是不是会崩掉呢?欢迎大家踊跃尝试^@^。 方法2、...

    如果要想实现文件的拷贝操作,有以下两种方法:
    方法1、将所有文件的内容一次性读取到程序之中,然后一次性输出;这样的话就需要开启一个跟文件一样大小的数据用于临时保存这些数据,但是当文件过大的时候呢?程序是不是会崩掉呢?欢迎大家踊跃尝试^@^。
    方法2、采用边读边写的操作,这样一来效率也提高了,也不会占用过多的内存空间。

    所以,我们采用第二种方法,边读边写。

    package signal.IO;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class CopyFile {
    
        /**
         * 定义一个方法来实现拷贝文件的功能
         * 
         * @param src 源文件路径
         * @param target 目标文件路径 
         * @throws IOException
         */
    
        public static void CopyFile(File src, File target) throws IOException{
            /**
             * 验证源文件是否存在
             */
            if(!src.exists()){
                System.err.println("There is no such a file !!!");
                System.exit(1);
            }
            /**
             * 验证目标路径是否存在,不存在的话创建父路径
             */
            if(!target.getParentFile().exists()){
                target.getParentFile().mkdirs();
            }
    
            int temp = 0;   //用作标示是否读取到源文件最后
            InputStream input = new FileInputStream(src);
            OutputStream output = new FileOutputStream(target);
    
            while((temp = input.read()) != -1){
                output.write(temp);
            }
    
            input.close();
            output.close();
        }
    
        public static void main(String[] args) {
    
            String in = "C:\\Users\\Administrator\\Desktop\\tmp.txt";//源文件路径
            String out = "C:\\Users\\Administrator\\Desktop\\tmp_copy.txt";//目标路径(此时还可以重命名)
    
            File src = new File(in);
            File target = new File(out);
    
            try {
                CopyFile(src, target);
                System.out.println("Copy Successfully !");
            } catch (IOException e) {
                System.err.println("ERROR: Something wrong while copying !");
                e.printStackTrace();
            }
        }
    }
    

    正如代码中写的那样,我们是一边读取一边写入。使用到的 read() 方法源码如下:

        ...
    
         /**
         * Reads the next byte of data from the input stream. The value byte is
         * returned as an <code>int</code> in the range <code>0</code> to
         * <code>255</code>. If no byte is available because the end of the stream
         * has been reached, the value <code>-1</code> is returned. This method
         * blocks until input data is available, the end of the stream is detected,
         * or an exception is thrown.
         *
         * <p> A subclass must provide an implementation of this method.
         *
         * @return     the next byte of data, or <code>-1</code> if the end of the
         *             stream is reached.
         * @exception  IOException  if an I/O error occurs.
         */
        public abstract int read() throws IOException;
    
        ...

    里面写到,”@return the next byte of data, or -1 if the end of the stream is reached.”,read() 方法的返回值为 “-1” 时表示文件读取完毕。这样一来就不难解释:

        while((temp = input.read()) != -1){
            output.write(temp);
        }

    有了这个基础,我们就可以再稍微改进一下,不要一次一个字节一个字节的读取和写入了。版本2如下:

    package signal.IO;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    public class CopyFileVersion2 {
    
        /**
         * 定义一个方法来实现拷贝文件的功能
         * 
         * @param src 源文件路径
         * @param target 目标文件路径 
         * @throws IOException
         */
    
        public static void CopyFile(File src, File target) throws IOException{
            /**
             * 验证源文件是否存在
             */
            if(!src.exists()){
                System.err.println("There is no such a file !!!");
                System.exit(1);
            }
            /**
             * 验证目标路径是否存在,不存在的话创建父路径
             */
            if(!target.getParentFile().exists()){
                target.getParentFile().mkdirs();
            }
    
            int temp = 0;   
    
            byte data[] = new byte[1024];   //每次读取1024字节
    
            InputStream input = new FileInputStream(src);
            OutputStream output = new FileOutputStream(target);
    
            while((temp = input.read(data)) != -1){
                output.write(data,0,temp);
            }
    
            input.close();
            output.close();
        }
    
        public static void main(String[] args) {
            String in = "C:\\Users\\Administrator\\Desktop\\tmp.txt";
            String out = "C:\\Users\\Administrator\\Desktop\\tmp_copy.txt";
    
            File src = new File(in);
            File target = new File(out);
    
            try {
    
                long start = System.currentTimeMillis();
                CopyFile(src, target);
                long end = System.currentTimeMillis();
    
                System.out.println("Copy Successfully! \nAnd it costs us " + (end - start) + " milliseconds.");
            } catch (IOException e) {
                System.err.println("ERROR: Something wrong while copying !");
                e.printStackTrace();
            }
        }
    }
    

    很明显可以看出不同,这里我们定义了一个1024字节的数组,这个数组的大小由自己来决定,其实这就是与第一种方法的结合。
    这里我们用到 read() 和 write() 两个方法也跟之前不同了,是带参数的。

    read( byte b[] ) 源码如下:

        /**
         * Reads some number of bytes from the input stream and stores them into
         * the buffer array <code>b</code>. The number of bytes actually read is
         * returned as an integer.  This method blocks until input data is
         * available, end of file is detected, or an exception is thrown.
         *
         * <p> If the length of <code>b</code> is zero, then no bytes are read and
         * <code>0</code> is returned; otherwise, there is an attempt to read at
         * least one byte. If no byte is available because the stream is at the
         * end of the file, the value <code>-1</code> is returned; otherwise, at
         * least one byte is read and stored into <code>b</code>.
         *
         * <p> The first byte read is stored into element <code>b[0]</code>, the
         * next one into <code>b[1]</code>, and so on. The number of bytes read is,
         * at most, equal to the length of <code>b</code>. Let <i>k</i> be the
         * number of bytes actually read; these bytes will be stored in elements
         * <code>b[0]</code> through <code>b[</code><i>k</i><code>-1]</code>,
         * leaving elements <code>b[</code><i>k</i><code>]</code> through
         * <code>b[b.length-1]</code> unaffected.
         *
         * <p> The <code>read(b)</code> method for class <code>InputStream</code>
         * has the same effect as: <pre><code> read(b, 0, b.length) </code></pre>
         *
         * @param      b   the buffer into which the data is read.
         * @return     the total number of bytes read into the buffer, or
         *             <code>-1</code> if there is no more data because the end of
         *             the stream has been reached.
         * @exception  IOException  If the first byte cannot be read for any reason
         * other than the end of the file, if the input stream has been closed, or
         * if some other I/O error occurs.
         * @exception  NullPointerException  if <code>b</code> is <code>null</code>.
         * @see        java.io.InputStream#read(byte[], int, int)
         */
        public int read(byte b[]) throws IOException {
            return read(b, 0, b.length);
        }

    源码已经很清楚的写出来了,”@param b the buffer into which the data is read.”,参数是要读取到内存中的字节数组,如果再跟下去,我们发现,其实这个方法是调用了 read( byte b[] , int off , int len )
    这里写图片描述
    其实最后,还是使用的 read() 方法,我们只不过是调用了已经封装好的一些方法。

    对于 write( byte b[], int off, int len )方法,源码如下:

        /**
         * Writes <code>len</code> bytes from the specified byte array
         * starting at offset <code>off</code> to this output stream.
         * The general contract for <code>write(b, off, len)</code> is that
         * some of the bytes in the array <code>b</code> are written to the
         * output stream in order; element <code>b[off]</code> is the first
         * byte written and <code>b[off+len-1]</code> is the last byte written
         * by this operation.
         * <p>
         * The <code>write</code> method of <code>OutputStream</code> calls
         * the write method of one argument on each of the bytes to be
         * written out. Subclasses are encouraged to override this method and
         * provide a more efficient implementation.
         * <p>
         * If <code>b</code> is <code>null</code>, a
         * <code>NullPointerException</code> is thrown.
         * <p>
         * If <code>off</code> is negative, or <code>len</code> is negative, or
         * <code>off+len</code> is greater than the length of the array
         * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown.
         *
         * @param      b     the data.
         * @param      off   the start offset in the data.
         * @param      len   the number of bytes to write.
         * @exception  IOException  if an I/O error occurs. In particular,
         *             an <code>IOException</code> is thrown if the output
         *             stream is closed.
         */
        public void write(byte b[], int off, int len) throws IOException {
            if (b == null) {
                throw new NullPointerException();
            } else if ((off < 0) || (off > b.length) || (len < 0) ||
                       ((off + len) > b.length) || ((off + len) < 0)) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return;
            }
            for (int i = 0 ; i < len ; i++) {
                write(b[off + i]);
            }
        }

    同样的,这个方法也是对 write( int b ) 方法的封装。
    另外我加了可以测试耗费时间的一个小功能,原理很简单,就是使用 currentTimeMillis() 方法,源码如下:

        /**
         * Returns the current time in milliseconds.  Note that
         * while the unit of time of the return value is a millisecond,
         * the granularity of the value depends on the underlying
         * operating system and may be larger.  For example, many
         * operating systems measure time in units of tens of
         * milliseconds.
         *
         * <p> See the description of the class <code>Date</code> for
         * a discussion of slight discrepancies that may arise between
         * "computer time" and coordinated universal time (UTC).
         *
         * @return  the difference, measured in milliseconds, between
         *          the current time and midnight, January 1, 1970 UTC.
         * @see     java.util.Date
         */
        public static native long currentTimeMillis();

    可以看到,这个方法的返回值是当前时间到1970年1月1日的间隔,单位是毫秒。
    到此我们简单的文件拷贝功能就实现了,其实就是对于IO的一个实际应用。大家在学习的过程中可以追进源码去看,很多什么参数呀返回值什么的介绍的都很详细。用了这么长时间的Eclipse,是java程序员的真爱,代码提示的功能很给力,就怕有一天离开了Eclipse连”Hello World”都写不出来了^_^ 。相比大家在学习IO的时候,要么是看视频,要么是学院派,老师肯定会跟你说IO有多重要多重要,一定要学好,所以大家在学习的过程中不妨写几个小功能,以便于对IO更好的掌握。这次我只是一时兴起,不代表这就是最终的实现,大家可以结合自己学到东西,随意改我的代码,但是别忘了自己的目的。

    展开全文
  • 我们这个功能, 实际上是加强了Windows安全。  支持多种光盘映像格式,使得WinMount成为一个虚拟光驱软件,包括:  * mou  * ISO  * cue/bin  * ccd (CloneCD)  * bwt (Blindwrite)  * mds (Media...
  • 本文主要针对自己在Winform方面缓存使用做一个引导性的介绍,希望大家能够从中了解一些缓存使用场景和使用方法。缓存是一个中大型系统所必须考虑问题。为了避免每次请求都去访问后台资源(例如数据库),...
  • 这些信息除了可以帮助用户了解特征以外,对一些重要功能的实现也是必要的,如输入字符的过滤、量规的显示和输入、自动计算和写入以及显示文件汇编等。 2.4.5 自定义的检查、测试和试验 自定义的检查、测试和试验指...
  •  作者不仅强调案例实用和可操作,更着重再现解决问题过程和思路并总结经验教训,希望将多年积累工作方法,以及对dba职业发展感悟展现出来,供广大oracle dba借鉴参考。 作译者  盖国强 网名Eygle ...
  • 它不需要临时变量就可以交换a和b值。 3.5 可否用显式括号来强制执行我所需要计算顺序并控制相关副作用?就算括号不行,操作符优先级是否能够控制计算顺序呢? 3.6 可是&&和||操作符呢?我看到过类似while((c...
  • Python 3.6.1对标准库进行了重大改进,asyncio模板添加了很多新的功能,从Python3.6开始 asyncio模板不再是临时的并且API变得更加稳定,安全也得到了大大的提高。使用方法:Python是一个解释语言,因为不需要...

    Python(python web开发)是全新一款功能强大的编程工具。Python 3.6.1对标准库进行了重大的改进,asyncio模板添加了很多新的功能,从Python3.6开始 asyncio模板不再是临时的并且API变得更加稳定,安全性也得到了大大的提高。

    使用方法:

    Python是一个解释性语言,因为不需要编译和连接所以能节省大量的程序开发时间。解释程序可以交互使用,这样可以可以很容易地试验语言的各种特色,写只用一次的程序,或在从底向上程序开发中测试函数。它也是一个方便的计算器。

    Python是一种面向对象、直译式计算机程序设计语言,也是一种功能强大而完善的通用型语言,已经具有十多年的发展历史,成熟且稳定。这种语言具有非常简捷而清晰的语法特点,适合完成各种高层任务,几乎可以在所有的操作系统中运行。目前,基于这种语言的相关技术正在飞速的发展,用户数量急剧扩大,相关的资源非常多。

    特点:Python允许你写出非常严谨而且可读的程序。用Python写的程序通常都比相应的C程序要短,因为如下几个理由:

    高级的数据结构允许你用一个语句表达复杂的操作;

    复合语句是靠缩进而不是用表示开始和结束的括号;

    不需要变量声明或参量声明。

    Python是可扩充的:如果你会用C语言编程就很容易为解释程序增加新的内置函数或模块,这样可以以最快速度执行关键操作,或把Python程序和只能以二进制码提供的库(如不同厂商提供的图形库)连接起来。当你变得确实很在行时你可以把Python解释器与用C写的应用相连接,把它作为该应用的扩展或命令语言。

    Python的命名是由BBC的“Monty Python's Flying Circus”节目而得,与蟒蛇没有什么关系。

    软件特性:

    一、新的语法特性

    1.PEP 498, 格式化字符串变量.

    2.PEP 515, 数字变量使用下划线.

    3.PEP 526, 给变量添加注释的语法.

    4.PEP 525, 异步生成器.

    5.PEP 530: 异步推导.

    二、新的库模板

    secrets: PEP 506 – Adding A Secrets Module To The Standard Library.

    三、CPython的一些改进

    1.重新实现了字典dict,使其更加紧凑,像是PyPy中的实现。此次重新实现的dict比Python3.5中的字典内存使用减少了20%-25%

    2.定制类的创建使用 new protocol 进行了简化

    3.类中各个属性定义的顺序现在是被保存的 now preserved.

    4.双星号变量**kwargs中的元素的顺序是你传入函数中的元素的顺序

    5.添加了DTrace和SystemTap探测支持。

    6.新的PYTHONMALLOC环境变量现在可用于调试解释器内存分配和访问错误。

    四、标准库的重大改进

    1.asyncio模板添加了很多新的功能、重要的可用性、性能改进以及大量的bug,从Python3.6开始 asyncio模板不再是临时的并且API变得更加稳定

    2.一个新的文件系统路径协议file system path protocol已经产生来支持 path-like objects,标准库中所有的文件路径操作已经被更新到使用新的协议

    3.datetime模板现在已经支持 Local Time Disambiguation

    4.typing模板进行了很多的改进

    5.tracemalloc模板进行了大幅度的改进,现在用来为ResourceWarning提供更好的输出、以及为内存分配错误提供更好的诊断。

    五、安全性的提高

    1.添加了新的模板secrets以简化使用于管理密码,比如账号认证,令牌等的密码的随机数的生成

    2.在Linux OS中,os.urandom()现在阻塞,直到系统urandom熵池被初始化以增加安全

    3.hashlib和ssl 模板现在已经支持OpenSSL 1.1.0.

    4.ssl 模板中的默认设置和功能现在已经被改进了

    5.模板现在新增了对BLAKE2, SHA-3 and SHAKE的哈希算法以及scrypt()密钥导出函数的支持

    展开全文
  • js笔记1

    2019-06-20 14:56:21
    脚本编程语言 特定描述语言 可以减少网页规模,提高网页浏览速度,丰富页面的功能 HTML 基本结构创建 可以理解为骨架 CSS 进行美化 使页面更漂亮 JS 实现功能 JS浏览器自带,不需要额外安装 页面使用JS...

    JavaScript入门(简称js)
    脚本编程语言 特定的描述性语言 可以减少网页的规模,提高网页的浏览速度,丰富页面的功能
    HTML 基本结构的创建 可以理解为骨架
    CSS 进行美化 使页面更漂亮
    JS 实现功能
    JS浏览器自带,不需要额外的安装

    页面使用JS的方法
    使用

    引用外部JS文件

    可以在任何一个位置写javascript

    JS变量 与其他程序设计语言相同,是用来临时存储信息
    创建方法1 var x=1;
    创建方法2 var x; x=1;弱数据类型 创建时候不区分
    注:JS中的变量,区分类型,但没有int之类的关键词
    JS调试 alert弹框调试 Console.log控制台输出调试
    作用 观察变量值的变化规律 是否符合程序的设计目的

    自定义函数 自定义函数是完成某一功能的代码段,可重复执行,方便管理和维护。
    创建方法1 这种事函数声明 可以使用后定义
    function fun1()
    {代码片段
    return ***}
    创建方法2 这种叫做函数表达式 必须先定义后使用
    var fun1=funtion(x){
    return x+1;}
    形参 定义时
    实参 调用时
    谁调用 谁得到return的值

    数据类型及类型转换
    定义时不区分 使用时区分
    number 数字类型 整型浮点型都包括
    string 字符串类型 必须放在单引号或者双引号中
    boolean 布尔类型 只有true和false两种值
    underline 未定义 一般指的是已经声明,但是没有赋值的变量 未被赋值 要避免 相当于一种错误
    null 空对象类型 var a=null 和var a =""有区别
    特殊类型
    object 对象类型 在js常见的有window document array 等
    NaN 是Number的一种特殊的类型 isNaN(),如果数字返回false,不是数字返回true(字符数字目前开来也是数字)是判断能不能转换的这个函数
    类型转换 parseInt() parseFloat() Number() Boolean()
    作用 强制类型转换 隐式类型转换(自动转换)
    优先使用Num
    parseInt 不进行四舍五入
    Boolean

    作用域
    局部变量 在函数内部创建的变量,称为局部变量,其他函数不能使用。
    全局变量 在函数外部创建的变量,称为全局变量,在函数之间可以共享使用。

    运算符
    比较运算符 用于比较两个值。结果是ture或者false
    运算符范围 > >= != < <=
    赋值运算符级别比><级别低
    运算符优先级
    1()
    2++ –
    3* / %
    4 + -
    5< <= >=
    6 == !=等于 不等于
    7&& 逻辑与
    8|| 逻辑或
    9?: 三目运算符
    10= 赋值
    三目运算符 根据不同的条件,执行不同的操作/返回不同的值
    格式 条件?值1:值2
    逻辑运算符 包含逻辑与,或,非等,其结果为true或false
    格式 && and
    || or
    ! 非

    程序控制语句
    条件判断类控制语句
    if else if else
    多条件分支类控制语句演示
    switch(x){
    case 只能是一个数字: break
    case :break
    default:
    } 不加break ,不会终止
    循环类控制语句
    for循环 while循环 do-while循环
    内置函数
    字符函数 substring substr charAt split length indexOf concat replace
    日期函数 Date getDate getDay getMonth getFullYear getHours
    getMinutes getSeconds
    数学函数 Math.round max min abs
    转化函数的 parseInt parseFloat Number Boolean

    字符函数
    substr(x,y) 截取从x开始的y位 起始位置 长度
    console.log(所截取数据.substr(x,y));
    substring(x,y)截取x开始y结束 算前不算后 不包括y 起始位置 结束位置
    charAt (x) 获取x位置的数
    x.length 获取x的长度
    x.indexOf(j) 查找j在x里面第一次出现的位置
    x.indexOf(j,k) 查找j在x里面,位置k之后出现的第一次的位置,位置顺序没有改变
    var x=y.split(“j”); 以j作为分隔 将y作为数组存到x里面
    y.concat(“aa”,“bb”);在y的基础上在输入aa,bb ,aa bb输入形式需要看y的形式 若y为数组则输入形式为数组 若为字符串则为字符串
    y.replace(“a”, “b”); 将y中的第一个a替换为b 注:只替换第一个符合要求的字符串。

    日期函数
    var d1 = new Date(); 系统的时间
    var d2 = new Date(“2020-2-17 10:58:58”);
    console.log(d2.getDate()); 几号 17
    console.log(d2.getMonth()); 几月1 因为月份从0开始console.log(d2.getMonth()+1); 2
    console.log(d2.getFullYear()); 几年2020
    console.log(d2.getHours()); 小时
    console.log(d2.getMinutes()); 分钟
    console.log(d2.getSeconds()); 秒
    var n =d2.getTime()-d1.getTime();
    getTime()用来获取毫秒数
    console.log(parseInt(n/(24601000)));
    2020-1-1 15:22 日期格式化
    function fun_FmtDate(){
    var d1 = new Date();
    var yyyy,mm,dd,hh,mi,ss;
    var time;
    yyyy=d1.getFullYear();
    mm=d1.getMonth()+1;
    dd=d1.getDate();
    hh=d1.getHours();
    mi=d1.getMinutes();
    ss=d1.getSeconds();
    time=yyyy+"-"+mm+"-"+dd+"-"+hh+":"+mi+":"+ss;
    return time;
    }

    数学函数
    var n=16.6557
    console.log(math.round(n)); 四舍五入取整 17
    console.log(n.toFixed(2)); 保留两位小数
    console.log(Math.min(2,6,77)); 2
    console.log(Math.max(2,6,77)); 77
    console.log(Math.abs(-3)); 3

    数组
    声明或创建一个不指定长度的数组,又称实例化创建
    var arrayObj=new Array();
    声明或创建一个数组并指定长度的数组
    var arrayObj=new Array(5);
    声明或创建一个带有默认值得数组
    var arrayObj=new Array(2,4,“a”,“y”,8);
    创建一个数组并赋值的简写,又称隐式创建数据
    var arrayObj=[2,4,“a”,“y”,8];
    数组赋值,字符下标,数组遍历
    console.log(arrayObj[0]);
    for(var i in arrayObj){
    console.log(i); 专门针对于数组,集合框架的for
    } 现在输出的是 0 1 2 3 4 5
    应该改为
    for(var i in arrayObj){
    console.log(arrayObj[i]);
    }
    var i=0;
    var n=arrayObj.length;
    for(i;i<n;i++){
    console.log(arrayObj[i]);
    }还是用 上面的那个比这个好

    什么是表单 表单的主要作用是客户端接收用户的信息,然后将数据递交给后台的程序来操控这些数据
    JS做什么 设置或获取各种表单元素的值
    示例:利用js给列表框等表单元素初始化
    document.getElementById()按照元素的id来获取该元素
    document.getElementById(“userName”).value=“imooc”;

    刷新body中的内容 单选按钮 name用来分组 document.getElementsByName(); 按name来获取元素 elements 是复数 得到的是数组 男 女
    function show1(){ var xb=document.getElementsByName("xb"); var xbText; if(xb[0].checked);{ xbText=xb[0].value;} }else{ xbText=xb[1].value; } alert(xbText); }

    name给后台程序使用 id给js使用

    function ymd(){ var yyyy=document.getElementById("yyyy"); for(var i=1999;i<=2019;i++){ yyyy.options.add(new Option(i,i));第一个i是值value 第二个i是名字 } } 年月日代码 年 月 日 函数 function ymd(){ var yyyy=document.getElementById("yyyy"); var mm=document.getElementById("mm"); var dd=document.getElementById("dd"); var date=new Date(); var year=parseInt(date.getFullYearr()); 解决年份变化问题 for(var i=1999;i<=year;i++){ yyyy.options.add(new Option(i,i)); } for(var i=1;i<=12;i++){ mm.options.add(new Option(i,i)); } for(var i=1;i<=31;i++){ dd.options.add(new Option(i,i)); } } 给列表框赋值,传递 表单元素 开始 结束值 function initSelect(object,start,end){ for(var i=start;i<=end;i++){ obj.options.add(new Option(i,i)); } 所以上面可以改成 var yyyy=document.getElementById("yyyy"); initSelect(yyyy,1999,year); } 实现中间年默认 var n=yyyy.length; yyyy.selectedIndex=Math.round(n/2);

    yyyy.options.length=0;将yyyy列表框中的条目变为0

    function selectYmd(){
    var mm=document.getElementById(“mm”);
    var dd=document.getElementById(“dd”);
    var m=parseInt(mm.value);
    var d=dayEnd;
    if(m4||m6||m9||m11){
    dayEnd=30;
    }else if(m2){
    dayEnd=28;
    y=parseInt(yyyy.value);
    if(y%4
    0&&y%100!=0||y%400==0){
    dayEnd=29;
    }
    }else{
    dayEnd=31;
    }
    dd.options.length=0;
    initSelect(dd,1,dayEnd);
    }
    οnchange="" 改变事件
    以上为年月日三级联动

    function deleteSelect(){
    var dd=document.getElementById(“dd”);
    dd.options.remove(1);
    for(i=0;i<dd.length;i++){
    dd.options.remove(i); 会变成隔一个删一个 得变成
    for(i=dd.length;i>=0;;i–){
    dd.options.remove(0);
    }
    }

    图片的切换


    function initLogo(){
    var logo=document.getElementById(“logo”);
    for(i=1;i<=15;i++){
    logo.options.add(new Option(i,i));
    }
    function selectLogo(){
    var logo=document.getElementById(“logo”);
    var n=logo.value;
    var logoImg=document.getElementById(“LogoImg”);
    logoImg.src=“image/headLogo/”+“n”+.gif"
    }
    }

    function checkInterest(){
    var interest=document.getElementsByName(“interest”);
    for(i=0;i<interest.length;i++){
    interest[i].checked=true;
    }
    function checkInterest1(){
    var interest=document.getElementsByName(“interest”);
    for(i=0;i<interest.length;i++){
    interest[i].checked=false;
    }
    代码优化
    var flag=true;
    function checkInterest(){
    var interest=document.getElementsByName(“interest”);
    for(i=0;i<interest.length;i++){
    interest[i].checked=flag;
    }
    if(flag=true){
    document.getElementById(“btn1”).value=“全不选”;
    }else{
    document.getElementById(“btn1”).value=“全选”;
    }
    function checkInterest1(){
    var interest=document.getElementsByName(“interest”);
    for(i=0;i<interest.length;i++){
    interest[i].checked=flag;
    }
    }

    什么是事件 事件是指被程序发现的行为或发生的事情,而且他可能会被程序处理(在什么时候发生什么事情)
    特点 js的事件,都是以on开头,有onclick,onchange,onload…
    事件分类 键盘事件 鼠标事件 表单事件…
    鼠标事件 onclick,ondblclick onmouseover onmouseout onmousedown
    键盘事件 onkeydown onkeyup keypress
    表单事件 onfoucs onsubmit onblur onblur onchange

    DOM Document Object Model
    文档对象模型
    什么是DOM 将文档(页面)表现为结构化的表示方法,使每一个页面元素都是可操控,DOM将网页和脚本以及其他的编程语言联系了起来
    特点 利用js控制页面中的所有元素,使页面更加“聪明”
    分类 元素节点 属性节点 文本节点 元素title 文档标题
    元素head 元素meta 属性charset(字符集)
    文档 根元素HTML
    元素body 元素a 文本 链接内容
    属性 href
    元素h1 文本 文本内容
    常用DOM操作
    getElementById 返回带有指定ID的元素
    getElementsByTagName 返回包含带有指定标签名称的所有元素的 节点列表
    getElementsByClassName 返回包含带有指定类名的所有元素的节点列表
    getElementsByName 获取相同名称(name)的元素的节点列表
    通过id name获取元素
    通过标签名获取所有的标签
    改变HTML属性,列如 改变img的src属性

    展开全文
  • 所以,用户只要使用了带有自动定位功能的终端,在一般情况下只需要在目标物上制作条形“编码”和读取条形“编码”部分就足够了,而不需要人工输入所在位置的经纬度信息;即使在自动定位失败的情况下,也只需指定出...
  • 问卷信度检验采用邮寄和发放相结合的方法,对距离较远城市公共体育场馆主要是邮寄,对西安市的公共体育场馆采用亲自发放,共发问卷60份,回收58份,回收率达到96.7%,有效问卷56份,有效率达93.3%。问卷发放、回收...
  • c语言计算机二级.pptx

    2020-03-07 01:45:20
    3语句结构 在一行只写一条语句 程序编写优先考虑清晰 除非对效率有特殊要求程序编写要清晰第一效率第二 首先要保证程序正确然后才要求提高速度 避免使用临时变量而是程序可读性下降 避免不必要转移 尽量能...
  • 《你必须知道495个C语言问题》

    热门讨论 2010-03-20 16:41:18
    它不需要临时变量就可以交换a和b值。 34 3.5 可否用显式括号来强制执行我所需要计算顺序并控制相关副作用?就算括号不行,操作符优先级是否能够控制计算顺序呢? 35  3.6 可是&&和||操作符呢?我看到过...
  • 它不需要临时变量就可以交换a和b值。 34 3.5 可否用显式括号来强制执行我所需要计算顺序并控制相关副作用?就算括号不行,操作符优先级是否能够控制计算顺序呢? 35  3.6 可是&&和||操作符呢?我看到过...
  • 4.7.7 用文件组提高VLDB可管理 162 4.7.8 用数据压缩减少磁盘空间使用 164 第5章 索引 167 5.1 索引预览 167 5.1.1 创建表索引 169 5.1.2 在非键列上强制唯一 170 5.1.3 在多个列上创建索引 171 ...
  • 软件工程知识点

    2012-12-02 21:34:25
    详细设计需要从实现每个模块功能的程序算法和模块内部的局部数据结构等细节内容上给出设计说明,并以“详细设计说明书”的形式提交书面报告。 3.编码和单元测试 编码是对软件的实现,一般由程序员完成,并以获得源...
  • 深入理解java反射原理

    2018-12-15 22:16:00
    反射是java一个特性,这一特性也使得它给...可以极大地提高应用扩展!  但是,除了停留在使用其华丽功能,我们还可以去看看其实现! 主要看两个方法的使用: 来个例子! public class HelloReflect { ...

      反射是java的一个特性,这一特性也使得它给了广大的第三方框架和开发过者很大的想像空间。

      通过反射,java可以动态的加载未知的外部配置对象,临时生成字节码进行加载使用,从而使代码更灵活!可以极大地提高应用的扩展性!

      但是,除了停留在使用其华丽功能,我们还可以去看看其实现!

    主要看两个方法的使用:

    来个例子!

    public class HelloReflect {
        public static void main(String[] args) {
            try {
                // 1. 使用外部配置的实现,进行动态加载类
                TempFunctionTest test = (TempFunctionTest)Class.forName("com.tester.HelloReflect").newInstance();
                test.sayHello("call directly");
                // 2. 根据配置的函数名,进行方法调用(不需要通用的接口抽象)
                Object t2 = new TempFunctionTest();
                Method method = t2.getClass().getDeclaredMethod("sayHello", String.class);
                method.invoke(test, "method invoke");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e ) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        
        public void sayHello(String word) {
            System.out.println("hello," + word);
        }
    
    }

      运行结果显而易见!我们来看执行流程!

    1. 反射获取类实例 Class.forName("C.a.xxx");

      首先调用了 java.lang.Class 的静态方法,获取类信息!

        @CallerSensitive
        public static Class<?> forName(String className)
                    throws ClassNotFoundException {
            // 先通过反射,获取调用进来的类信息,从而获取当前的 classLoader
            Class<?> caller = Reflection.getCallerClass();
            // 调用native方法进行获取class信息
            return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
        }

      forName()反射获取类信息,并没有将实现留给了java,而是交给了jvm去加载!

      主要是先获取 ClassLoader, 然后调用 native 方法,获取信息,加载类则是回调 java.lang.ClassLoader.

      最后,jvm又会回调 ClassLoader 进类加载!

        // 
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            return loadClass(name, false);
        }
        
            // sun.misc.Launcher
            public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException {
                int var3 = var1.lastIndexOf(46);
                if(var3 != -1) {
                    SecurityManager var4 = System.getSecurityManager();
                    if(var4 != null) {
                        var4.checkPackageAccess(var1.substring(0, var3));
                    }
                }
    
                if(this.ucp.knownToNotExist(var1)) {
                    Class var5 = this.findLoadedClass(var1);
                    if(var5 != null) {
                        if(var2) {
                            this.resolveClass(var5);
                        }
    
                        return var5;
                    } else {
                        throw new ClassNotFoundException(var1);
                    }
                } else {
                    return super.loadClass(var1, var2);
                }
            }
        // java.lang.ClassLoader
        protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException
        {
            // 先获取锁
            synchronized (getClassLoadingLock(name)) {
                // First, check if the class has already been loaded
                // 如果已经加载了的话,就不用再加载了
                Class<?> c = findLoadedClass(name);
                if (c == null) {
                    long t0 = System.nanoTime();
                    try {
                        // 双亲委托加载
                        if (parent != null) {
                            c = parent.loadClass(name, false);
                        } else {
                            c = findBootstrapClassOrNull(name);
                        }
                    } catch (ClassNotFoundException e) {
                        // ClassNotFoundException thrown if class not found
                        // from the non-null parent class loader
                    }
    
                    // 父类没有加载到时,再自己加载
                    if (c == null) {
                        // If still not found, then invoke findClass in order
                        // to find the class.
                        long t1 = System.nanoTime();
                        c = findClass(name);
    
                        // this is the defining class loader; record the stats
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
        
        protected Object getClassLoadingLock(String className) {
            Object lock = this;
            if (parallelLockMap != null) {
                // 使用 ConcurrentHashMap来保存锁
                Object newLock = new Object();
                lock = parallelLockMap.putIfAbsent(className, newLock);
                if (lock == null) {
                    lock = newLock;
                }
            }
            return lock;
        }
        
        protected final Class<?> findLoadedClass(String name) {
            if (!checkName(name))
                return null;
            return findLoadedClass0(name);
        }

      下面来看一下 newInstance() 的实现方式!

        // 首先肯定是 Class.newInstance
        @CallerSensitive
        public T newInstance()
            throws InstantiationException, IllegalAccessException
        {
            if (System.getSecurityManager() != null) {
                checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false);
            }
    
            // NOTE: the following code may not be strictly correct under
            // the current Java memory model.
    
            // Constructor lookup
            // newInstance() 其实相当于调用类的无参构造函数,所以,首先要找到其无参构造器
            if (cachedConstructor == null) {
                if (this == Class.class) {
                    // 不允许调用 Class 的 newInstance() 方法
                    throw new IllegalAccessException(
                        "Can not call newInstance() on the Class for java.lang.Class"
                    );
                }
                try {
                    // 获取无参构造器
                    Class<?>[] empty = {};
                    final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
                    // Disable accessibility checks on the constructor
                    // since we have to do the security check here anyway
                    // (the stack depth is wrong for the Constructor's
                    // security check to work)
                    java.security.AccessController.doPrivileged(
                        new java.security.PrivilegedAction<Void>() {
                            public Void run() {
                                    c.setAccessible(true);
                                    return null;
                                }
                            });
                    cachedConstructor = c;
                } catch (NoSuchMethodException e) {
                    throw (InstantiationException)
                        new InstantiationException(getName()).initCause(e);
                }
            }
            Constructor<T> tmpConstructor = cachedConstructor;
            // Security check (same as in java.lang.reflect.Constructor)
            int modifiers = tmpConstructor.getModifiers();
            if (!Reflection.quickCheckMemberAccess(this, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                if (newInstanceCallerCache != caller) {
                    Reflection.ensureMemberAccess(caller, this, null, modifiers);
                    newInstanceCallerCache = caller;
                }
            }
            // Run constructor
            try {
                // 调用无参构造器
                return tmpConstructor.newInstance((Object[])null);
            } catch (InvocationTargetException e) {
                Unsafe.getUnsafe().throwException(e.getTargetException());
                // Not reached
                return null;
            }
        }

     newInstance() 主要做了三件事:

      1. 权限检测,如果不通过直接抛出异常;

      2. 查找无参构造器,并将其缓存起来;

      3. 调用具体方法的无参构造方法,生成实例并返回;

    下面是获取构造器的过程:

        private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                            int which) throws NoSuchMethodException
        {
            // 获取所有构造器
            Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
            for (Constructor<T> constructor : constructors) {
                if (arrayContentsEq(parameterTypes,
                                    constructor.getParameterTypes())) {
                    return getReflectionFactory().copyConstructor(constructor);
                }
            }
            throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
        }

    getConstructor0() 为获取匹配的构造方器;分三步:
      1. 先获取所有的constructors, 然后通过进行参数类型比较;
      2. 找到匹配后,通过 ReflectionFactory copy一份constructor返回;
      3. 否则抛出 NoSuchMethodException;

        // 获取当前类所有的构造方法,通过jvm或者缓存
        // Returns an array of "root" constructors. These Constructor
        // objects must NOT be propagated to the outside world, but must
        // instead be copied via ReflectionFactory.copyConstructor.
        private Constructor<T>[] privateGetDeclaredConstructors(boolean publicOnly) {
            checkInitted();
            Constructor<T>[] res;
            // 调用 reflectionData(), 获取保存的信息,使用软引用保存,从而使内存不够可以回收
            ReflectionData<T> rd = reflectionData();
            if (rd != null) {
                res = publicOnly ? rd.publicConstructors : rd.declaredConstructors;
                // 存在缓存,则直接返回
                if (res != null) return res;
            }
            // No cached value available; request value from VM
            if (isInterface()) {
                @SuppressWarnings("unchecked")
                Constructor<T>[] temporaryRes = (Constructor<T>[]) new Constructor<?>[0];
                res = temporaryRes;
            } else {
                // 使用native方法从jvm获取构造器
                res = getDeclaredConstructors0(publicOnly);
            }
            if (rd != null) {
                // 最后,将从jvm中读取的内容,存入缓存
                if (publicOnly) {
                    rd.publicConstructors = res;
                } else {
                    rd.declaredConstructors = res;
                }
            }
            return res;
        }
        
        // Lazily create and cache ReflectionData
        private ReflectionData<T> reflectionData() {
            SoftReference<ReflectionData<T>> reflectionData = this.reflectionData;
            int classRedefinedCount = this.classRedefinedCount;
            ReflectionData<T> rd;
            if (useCaches &&
                reflectionData != null &&
                (rd = reflectionData.get()) != null &&
                rd.redefinedCount == classRedefinedCount) {
                return rd;
            }
            // else no SoftReference or cleared SoftReference or stale ReflectionData
            // -> create and replace new instance
            return newReflectionData(reflectionData, classRedefinedCount);
        }
        
        // 新创建缓存,保存反射信息
        private ReflectionData<T> newReflectionData(SoftReference<ReflectionData<T>> oldReflectionData,
                                                    int classRedefinedCount) {
            if (!useCaches) return null;
    
            // 使用cas保证更新的线程安全性,所以反射是保证线程安全的
            while (true) {
                ReflectionData<T> rd = new ReflectionData<>(classRedefinedCount);
                // try to CAS it...
                if (Atomic.casReflectionData(this, oldReflectionData, new SoftReference<>(rd))) {
                    return rd;
                }
                // 先使用CAS更新,如果更新成功,则立即返回,否则测查当前已被其他线程更新的情况,如果和自己想要更新的状态一致,则也算是成功了
                oldReflectionData = this.reflectionData;
                classRedefinedCount = this.classRedefinedCount;
                if (oldReflectionData != null &&
                    (rd = oldReflectionData.get()) != null &&
                    rd.redefinedCount == classRedefinedCount) {
                    return rd;
                }
            }
        }

    如上,privateGetDeclaredConstructors(), 获取所有的构造器主要步骤;
      1. 先尝试从缓存中获取;
      2. 如果缓存没有,则从jvm中重新获取,并存入缓存,缓存使用软引用进行保存,保证内存可用;

    另外,使用 relactionData() 进行缓存保存;ReflectionData 的数据结构如下!

        // reflection data that might get invalidated when JVM TI RedefineClasses() is called
        private static class ReflectionData<T> {
            volatile Field[] declaredFields;
            volatile Field[] publicFields;
            volatile Method[] declaredMethods;
            volatile Method[] publicMethods;
            volatile Constructor<T>[] declaredConstructors;
            volatile Constructor<T>[] publicConstructors;
            // Intermediate results for getFields and getMethods
            volatile Field[] declaredPublicFields;
            volatile Method[] declaredPublicMethods;
            volatile Class<?>[] interfaces;
    
            // Value of classRedefinedCount when we created this ReflectionData instance
            final int redefinedCount;
    
            ReflectionData(int redefinedCount) {
                this.redefinedCount = redefinedCount;
            }
        }

      其中,还有一个点,就是如何比较构造是否是要查找构造器,其实就是比较类型完成相等就完了,有一个不相等则返回false。

        private static boolean arrayContentsEq(Object[] a1, Object[] a2) {
            if (a1 == null) {
                return a2 == null || a2.length == 0;
            }
    
            if (a2 == null) {
                return a1.length == 0;
            }
    
            if (a1.length != a2.length) {
                return false;
            }
    
            for (int i = 0; i < a1.length; i++) {
                if (a1[i] != a2[i]) {
                    return false;
                }
            }
    
            return true;
        }
        // sun.reflect.ReflectionFactory
        /** Makes a copy of the passed constructor. The returned
            constructor is a "child" of the passed one; see the comments
            in Constructor.java for details. */
        public <T> Constructor<T> copyConstructor(Constructor<T> arg) {
            return langReflectAccess().copyConstructor(arg);
        }
        
        // java.lang.reflect.Constructor, copy 其实就是新new一个 Constructor 出来
        Constructor<T> copy() {
            // This routine enables sharing of ConstructorAccessor objects
            // among Constructor objects which refer to the same underlying
            // method in the VM. (All of this contortion is only necessary
            // because of the "accessibility" bit in AccessibleObject,
            // which implicitly requires that new java.lang.reflect
            // objects be fabricated for each reflective call on Class
            // objects.)
            if (this.root != null)
                throw new IllegalArgumentException("Can not copy a non-root Constructor");
    
            Constructor<T> res = new Constructor<>(clazz,
                                                   parameterTypes,
                                                   exceptionTypes, modifiers, slot,
                                                   signature,
                                                   annotations,
                                                   parameterAnnotations);
            // root 指向当前 constructor
            res.root = this;
            // Might as well eagerly propagate this if already present
            res.constructorAccessor = constructorAccessor;
            return res;
        }
        

      通过上面,获取到 Constructor 了!

    接下来就只需调用其相应构造器的 newInstance(),即返回实例了!

        // return tmpConstructor.newInstance((Object[])null); 
        // java.lang.reflect.Constructor
        @CallerSensitive
        public T newInstance(Object ... initargs)
            throws InstantiationException, IllegalAccessException,
                   IllegalArgumentException, InvocationTargetException
        {
            if (!override) {
                if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                    Class<?> caller = Reflection.getCallerClass();
                    checkAccess(caller, clazz, null, modifiers);
                }
            }
            if ((clazz.getModifiers() & Modifier.ENUM) != 0)
                throw new IllegalArgumentException("Cannot reflectively create enum objects");
            ConstructorAccessor ca = constructorAccessor;   // read volatile
            if (ca == null) {
                ca = acquireConstructorAccessor();
            }
            @SuppressWarnings("unchecked")
            T inst = (T) ca.newInstance(initargs);
            return inst;
        }
        // sun.reflect.DelegatingConstructorAccessorImpl
        public Object newInstance(Object[] args)
          throws InstantiationException,
                 IllegalArgumentException,
                 InvocationTargetException
        {
            return delegate.newInstance(args);
        }
        // sun.reflect.NativeConstructorAccessorImpl
        public Object newInstance(Object[] args)
            throws InstantiationException,
                   IllegalArgumentException,
                   InvocationTargetException
        {
            // We can't inflate a constructor belonging to a vm-anonymous class
            // because that kind of class can't be referred to by name, hence can't
            // be found from the generated bytecode.
            if (++numInvocations > ReflectionFactory.inflationThreshold()
                    && !ReflectUtil.isVMAnonymousClass(c.getDeclaringClass())) {
                ConstructorAccessorImpl acc = (ConstructorAccessorImpl)
                    new MethodAccessorGenerator().
                        generateConstructor(c.getDeclaringClass(),
                                            c.getParameterTypes(),
                                            c.getExceptionTypes(),
                                            c.getModifiers());
                parent.setDelegate(acc);
            }
    
            // 调用native方法,进行调用 constructor
            return newInstance0(c, args);
        }

      返回构造器的实例后,可以根据外部进行进行类型转换,从而使用接口或方法进行调用实例功能了。

    2. 反射获取方法 c.class.getDeclaredMethod();Method.invoke() 反射调用方法!

      第一步,先获取 Method; 

        // java.lang.Class
        @CallerSensitive
        public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
            throws NoSuchMethodException, SecurityException {
            checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
            Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes);
            if (method == null) {
                throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes));
            }
            return method;
        }

    忽略第一个检查权限,剩下就只有两个动作了!
      1. 获取所有方法列表;
      2. 根据方法名称和方法列表,选出符合要求的方法;
      3. 如果没有找到相应方法,抛出异常,否则返回对应方法;

      所以,先看一下怎样获取类声明的所有方法?

        // Returns an array of "root" methods. These Method objects must NOT
        // be propagated to the outside world, but must instead be copied
        // via ReflectionFactory.copyMethod.
        private Method[] privateGetDeclaredMethods(boolean publicOnly) {
            checkInitted();
            Method[] res;
            ReflectionData<T> rd = reflectionData();
            if (rd != null) {
                res = publicOnly ? rd.declaredPublicMethods : rd.declaredMethods;
                if (res != null) return res;
            }
            // No cached value available; request value from VM
            res = Reflection.filterMethods(this, getDeclaredMethods0(publicOnly));
            if (rd != null) {
                if (publicOnly) {
                    rd.declaredPublicMethods = res;
                } else {
                    rd.declaredMethods = res;
                }
            }
            return res;
        }

      很相似,和获取所有构造器的方法很相似,都是先从缓存中获取方法,如果没有,则从jvm中获取!

      不同的是,方法列表需要进行过滤 Reflection.filterMethods;当然后面看来,这个方法我们一般不会派上用场!

        // sun.misc.Reflection
        public static Method[] filterMethods(Class<?> containingClass, Method[] methods) {
            if (methodFilterMap == null) {
                // Bootstrapping
                return methods;
            }
            return (Method[])filter(methods, methodFilterMap.get(containingClass));
        }
        // 可以过滤指定的方法,一般为空,如果要指定过滤,可以调用 registerMethodsToFilter(), 或者...
        private static Member[] filter(Member[] members, String[] filteredNames) {
            if ((filteredNames == null) || (members.length == 0)) {
                return members;
            }
            int numNewMembers = 0;
            for (Member member : members) {
                boolean shouldSkip = false;
                for (String filteredName : filteredNames) {
                    if (member.getName() == filteredName) {
                        shouldSkip = true;
                        break;
                    }
                }
                if (!shouldSkip) {
                    ++numNewMembers;
                }
            }
            Member[] newMembers =
                (Member[])Array.newInstance(members[0].getClass(), numNewMembers);
            int destIdx = 0;
            for (Member member : members) {
                boolean shouldSkip = false;
                for (String filteredName : filteredNames) {
                    if (member.getName() == filteredName) {
                        shouldSkip = true;
                        break;
                    }
                }
                if (!shouldSkip) {
                    newMembers[destIdx++] = member;
                }
            }
            return newMembers;
        }

      第二步,根据方法名和参数类型过滤指定方法返回:

        private static Method searchMethods(Method[] methods,
                                            String name,
                                            Class<?>[] parameterTypes)
        {
            Method res = null;
            // 使用常量池,避免重复创建String
            String internedName = name.intern();
            for (int i = 0; i < methods.length; i++) {
                Method m = methods[i];
                if (m.getName() == internedName
                    && arrayContentsEq(parameterTypes, m.getParameterTypes())
                    && (res == null
                        || res.getReturnType().isAssignableFrom(m.getReturnType())))
                    res = m;
            }
    
            return (res == null ? res : getReflectionFactory().copyMethod(res));
        }

    大概意思看得明白,就是匹配到方法名,然后参数类型匹配,才可以!
      但是,可以看到,匹配到一个方法,并没有退出for循环,而是继续进行匹配!
      这里,是匹配最精确的子类进行返回(最优匹配)
      最后,还是通过 ReflectionFactory, copy 方法后返回!

    第三步,调用 method.invoke() 方法!

        @CallerSensitive
        public Object invoke(Object obj, Object... args)
            throws IllegalAccessException, IllegalArgumentException,
               InvocationTargetException
        {
            if (!override) {
                if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                    Class<?> caller = Reflection.getCallerClass();
                    checkAccess(caller, clazz, obj, modifiers);
                }
            }
            MethodAccessor ma = methodAccessor;             // read volatile
            if (ma == null) {
                ma = acquireMethodAccessor();
            }
            return ma.invoke(obj, args);
        }

      invoke时,是通过 MethodAccessor 进行调用的,而 MethodAccessor 是个接口,在第一次时调用 acquireMethodAccessor() 进行新创建!

        // probably make the implementation more scalable.
        private MethodAccessor acquireMethodAccessor() {
            // First check to see if one has been created yet, and take it
            // if so
            MethodAccessor tmp = null;
            if (root != null) tmp = root.getMethodAccessor();
            if (tmp != null) {
                // 存在缓存时,存入 methodAccessor,否则调用 ReflectionFactory 创建新的 MethodAccessor
                methodAccessor = tmp;
            } else {
                // Otherwise fabricate one and propagate it up to the root
                tmp = reflectionFactory.newMethodAccessor(this);
                setMethodAccessor(tmp);
            }
    
            return tmp;
        }
        // sun.reflect.ReflectionFactory
        public MethodAccessor newMethodAccessor(Method method) {
            checkInitted();
    
            if (noInflation && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
                return new MethodAccessorGenerator().
                    generateMethod(method.getDeclaringClass(),
                                   method.getName(),
                                   method.getParameterTypes(),
                                   method.getReturnType(),
                                   method.getExceptionTypes(),
                                   method.getModifiers());
            } else {
                NativeMethodAccessorImpl acc =
                    new NativeMethodAccessorImpl(method);
                DelegatingMethodAccessorImpl res =
                    new DelegatingMethodAccessorImpl(acc);
                acc.setParent(res);
                return res;
            }
        }

    两个Accessor详情:

    //     NativeMethodAccessorImpl / DelegatingMethodAccessorImpl
    class NativeMethodAccessorImpl extends MethodAccessorImpl {
        private final Method method;
        private DelegatingMethodAccessorImpl parent;
        private int numInvocations;
    
        NativeMethodAccessorImpl(Method method) {
            this.method = method;
        }
    
        public Object invoke(Object obj, Object[] args)
            throws IllegalArgumentException, InvocationTargetException
        {
            // We can't inflate methods belonging to vm-anonymous classes because
            // that kind of class can't be referred to by name, hence can't be
            // found from the generated bytecode.
            if (++numInvocations > ReflectionFactory.inflationThreshold()
                    && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
                MethodAccessorImpl acc = (MethodAccessorImpl)
                    new MethodAccessorGenerator().
                        generateMethod(method.getDeclaringClass(),
                                       method.getName(),
                                       method.getParameterTypes(),
                                       method.getReturnType(),
                                       method.getExceptionTypes(),
                                       method.getModifiers());
                parent.setDelegate(acc);
            }
    
            return invoke0(method, obj, args);
        }
    
        void setParent(DelegatingMethodAccessorImpl parent) {
            this.parent = parent;
        }
    
        private static native Object invoke0(Method m, Object obj, Object[] args);
    }
    class DelegatingMethodAccessorImpl extends MethodAccessorImpl {
        private MethodAccessorImpl delegate;
    
        DelegatingMethodAccessorImpl(MethodAccessorImpl delegate) {
            setDelegate(delegate);
        }
    
        public Object invoke(Object obj, Object[] args)
            throws IllegalArgumentException, InvocationTargetException
        {
            return delegate.invoke(obj, args);
        }
    
        void setDelegate(MethodAccessorImpl delegate) {
            this.delegate = delegate;
        }
    }
    View Code

      进行 ma.invoke(obj, args); 调用时,调用 DelegatingMethodAccessorImpl.invoke(); 

      最后被委托到 NativeMethodAccessorImpl.invoke(), 即:

        public Object invoke(Object obj, Object[] args)
            throws IllegalArgumentException, InvocationTargetException
        {
            // We can't inflate methods belonging to vm-anonymous classes because
            // that kind of class can't be referred to by name, hence can't be
            // found from the generated bytecode.
            if (++numInvocations > ReflectionFactory.inflationThreshold()
                    && !ReflectUtil.isVMAnonymousClass(method.getDeclaringClass())) {
                MethodAccessorImpl acc = (MethodAccessorImpl)
                    new MethodAccessorGenerator().
                        generateMethod(method.getDeclaringClass(),
                                       method.getName(),
                                       method.getParameterTypes(),
                                       method.getReturnType(),
                                       method.getExceptionTypes(),
                                       method.getModifiers());
                parent.setDelegate(acc);
            }
    
            // invoke0 是个 native 方法,由jvm进行调用业务方法!从而完成反射调用功能!
            return invoke0(method, obj, args);
        }
        

       其中, generateMethod() 是生成具体类的方法:

        
        /** This routine is not thread-safe */
        public MethodAccessor generateMethod(Class<?> declaringClass,
                                             String   name,
                                             Class<?>[] parameterTypes,
                                             Class<?>   returnType,
                                             Class<?>[] checkedExceptions,
                                             int modifiers)
        {
            return (MethodAccessor) generate(declaringClass,
                                             name,
                                             parameterTypes,
                                             returnType,
                                             checkedExceptions,
                                             modifiers,
                                             false,
                                             false,
                                             null);
        }

    generate() 戳详情!

        /** This routine is not thread-safe */
        private MagicAccessorImpl generate(final Class<?> declaringClass,
                                           String name,
                                           Class<?>[] parameterTypes,
                                           Class<?>   returnType,
                                           Class<?>[] checkedExceptions,
                                           int modifiers,
                                           boolean isConstructor,
                                           boolean forSerialization,
                                           Class<?> serializationTargetClass)
        {
            ByteVector vec = ByteVectorFactory.create();
            asm = new ClassFileAssembler(vec);
            this.declaringClass = declaringClass;
            this.parameterTypes = parameterTypes;
            this.returnType = returnType;
            this.modifiers = modifiers;
            this.isConstructor = isConstructor;
            this.forSerialization = forSerialization;
    
            asm.emitMagicAndVersion();
    
            // Constant pool entries:
            // ( * = Boxing information: optional)
            // (+  = Shared entries provided by AccessorGenerator)
            // (^  = Only present if generating SerializationConstructorAccessor)
            //     [UTF-8] [This class's name]
            //     [CONSTANT_Class_info] for above
            //     [UTF-8] "sun/reflect/{MethodAccessorImpl,ConstructorAccessorImpl,SerializationConstructorAccessorImpl}"
            //     [CONSTANT_Class_info] for above
            //     [UTF-8] [Target class's name]
            //     [CONSTANT_Class_info] for above
            // ^   [UTF-8] [Serialization: Class's name in which to invoke constructor]
            // ^   [CONSTANT_Class_info] for above
            //     [UTF-8] target method or constructor name
            //     [UTF-8] target method or constructor signature
            //     [CONSTANT_NameAndType_info] for above
            //     [CONSTANT_Methodref_info or CONSTANT_InterfaceMethodref_info] for target method
            //     [UTF-8] "invoke" or "newInstance"
            //     [UTF-8] invoke or newInstance descriptor
            //     [UTF-8] descriptor for type of non-primitive parameter 1
            //     [CONSTANT_Class_info] for type of non-primitive parameter 1
            //     ...
            //     [UTF-8] descriptor for type of non-primitive parameter n
            //     [CONSTANT_Class_info] for type of non-primitive parameter n
            // +   [UTF-8] "java/lang/Exception"
            // +   [CONSTANT_Class_info] for above
            // +   [UTF-8] "java/lang/ClassCastException"
            // +   [CONSTANT_Class_info] for above
            // +   [UTF-8] "java/lang/NullPointerException"
            // +   [CONSTANT_Class_info] for above
            // +   [UTF-8] "java/lang/IllegalArgumentException"
            // +   [CONSTANT_Class_info] for above
            // +   [UTF-8] "java/lang/InvocationTargetException"
            // +   [CONSTANT_Class_info] for above
            // +   [UTF-8] "<init>"
            // +   [UTF-8] "()V"
            // +   [CONSTANT_NameAndType_info] for above
            // +   [CONSTANT_Methodref_info] for NullPointerException's constructor
            // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor
            // +   [UTF-8] "(Ljava/lang/String;)V"
            // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/String;)V"
            // +   [CONSTANT_Methodref_info] for IllegalArgumentException's constructor taking a String
            // +   [UTF-8] "(Ljava/lang/Throwable;)V"
            // +   [CONSTANT_NameAndType_info] for "<init>(Ljava/lang/Throwable;)V"
            // +   [CONSTANT_Methodref_info] for InvocationTargetException's constructor
            // +   [CONSTANT_Methodref_info] for "super()"
            // +   [UTF-8] "java/lang/Object"
            // +   [CONSTANT_Class_info] for above
            // +   [UTF-8] "toString"
            // +   [UTF-8] "()Ljava/lang/String;"
            // +   [CONSTANT_NameAndType_info] for "toString()Ljava/lang/String;"
            // +   [CONSTANT_Methodref_info] for Object's toString method
            // +   [UTF-8] "Code"
            // +   [UTF-8] "Exceptions"
            //  *  [UTF-8] "java/lang/Boolean"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(Z)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "booleanValue"
            //  *  [UTF-8] "()Z"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Byte"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(B)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "byteValue"
            //  *  [UTF-8] "()B"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Character"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(C)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "charValue"
            //  *  [UTF-8] "()C"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Double"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(D)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "doubleValue"
            //  *  [UTF-8] "()D"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Float"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(F)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "floatValue"
            //  *  [UTF-8] "()F"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Integer"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(I)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "intValue"
            //  *  [UTF-8] "()I"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Long"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(J)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "longValue"
            //  *  [UTF-8] "()J"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "java/lang/Short"
            //  *  [CONSTANT_Class_info] for above
            //  *  [UTF-8] "(S)V"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
            //  *  [UTF-8] "shortValue"
            //  *  [UTF-8] "()S"
            //  *  [CONSTANT_NameAndType_info] for above
            //  *  [CONSTANT_Methodref_info] for above
    
            short numCPEntries = NUM_BASE_CPOOL_ENTRIES + NUM_COMMON_CPOOL_ENTRIES;
            boolean usesPrimitives = usesPrimitiveTypes();
            if (usesPrimitives) {
                numCPEntries += NUM_BOXING_CPOOL_ENTRIES;
            }
            if (forSerialization) {
                numCPEntries += NUM_SERIALIZATION_CPOOL_ENTRIES;
            }
    
            // Add in variable-length number of entries to be able to describe
            // non-primitive parameter types and checked exceptions.
            numCPEntries += (short) (2 * numNonPrimitiveParameterTypes());
    
            asm.emitShort(add(numCPEntries, S1));
    
            final String generatedName = generateName(isConstructor, forSerialization);
            asm.emitConstantPoolUTF8(generatedName);
            asm.emitConstantPoolClass(asm.cpi());
            thisClass = asm.cpi();
            if (isConstructor) {
                if (forSerialization) {
                    asm.emitConstantPoolUTF8
                        ("sun/reflect/SerializationConstructorAccessorImpl");
                } else {
                    asm.emitConstantPoolUTF8("sun/reflect/ConstructorAccessorImpl");
                }
            } else {
                asm.emitConstantPoolUTF8("sun/reflect/MethodAccessorImpl");
            }
            asm.emitConstantPoolClass(asm.cpi());
            superClass = asm.cpi();
            asm.emitConstantPoolUTF8(getClassName(declaringClass, false));
            asm.emitConstantPoolClass(asm.cpi());
            targetClass = asm.cpi();
            short serializationTargetClassIdx = (short) 0;
            if (forSerialization) {
                asm.emitConstantPoolUTF8(getClassName(serializationTargetClass, false));
                asm.emitConstantPoolClass(asm.cpi());
                serializationTargetClassIdx = asm.cpi();
            }
            asm.emitConstantPoolUTF8(name);
            asm.emitConstantPoolUTF8(buildInternalSignature());
            asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi());
            if (isInterface()) {
                asm.emitConstantPoolInterfaceMethodref(targetClass, asm.cpi());
            } else {
                if (forSerialization) {
                    asm.emitConstantPoolMethodref(serializationTargetClassIdx, asm.cpi());
                } else {
                    asm.emitConstantPoolMethodref(targetClass, asm.cpi());
                }
            }
            targetMethodRef = asm.cpi();
            if (isConstructor) {
                asm.emitConstantPoolUTF8("newInstance");
            } else {
                asm.emitConstantPoolUTF8("invoke");
            }
            invokeIdx = asm.cpi();
            if (isConstructor) {
                asm.emitConstantPoolUTF8("([Ljava/lang/Object;)Ljava/lang/Object;");
            } else {
                asm.emitConstantPoolUTF8
                    ("(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
            }
            invokeDescriptorIdx = asm.cpi();
    
            // Output class information for non-primitive parameter types
            nonPrimitiveParametersBaseIdx = add(asm.cpi(), S2);
            for (int i = 0; i < parameterTypes.length; i++) {
                Class<?> c = parameterTypes[i];
                if (!isPrimitive(c)) {
                    asm.emitConstantPoolUTF8(getClassName(c, false));
                    asm.emitConstantPoolClass(asm.cpi());
                }
            }
    
            // Entries common to FieldAccessor, MethodAccessor and ConstructorAccessor
            emitCommonConstantPoolEntries();
    
            // Boxing entries
            if (usesPrimitives) {
                emitBoxingContantPoolEntries();
            }
    
            if (asm.cpi() != numCPEntries) {
                throw new InternalError("Adjust this code (cpi = " + asm.cpi() +
                                        ", numCPEntries = " + numCPEntries + ")");
            }
    
            // Access flags
            asm.emitShort(ACC_PUBLIC);
    
            // This class
            asm.emitShort(thisClass);
    
            // Superclass
            asm.emitShort(superClass);
    
            // Interfaces count and interfaces
            asm.emitShort(S0);
    
            // Fields count and fields
            asm.emitShort(S0);
    
            // Methods count and methods
            asm.emitShort(NUM_METHODS);
    
            emitConstructor();
            emitInvoke();
    
            // Additional attributes (none)
            asm.emitShort(S0);
    
            // Load class
            vec.trim();
            final byte[] bytes = vec.getData();
            // Note: the class loader is the only thing that really matters
            // here -- it's important to get the generated code into the
            // same namespace as the target class. Since the generated code
            // is privileged anyway, the protection domain probably doesn't
            // matter.
            return AccessController.doPrivileged(
                new PrivilegedAction<MagicAccessorImpl>() {
                    public MagicAccessorImpl run() {
                            try {
                            return (MagicAccessorImpl)
                            ClassDefiner.defineClass
                                    (generatedName,
                                     bytes,
                                     0,
                                     bytes.length,
                                     declaringClass.getClassLoader()).newInstance();
                            } catch (InstantiationException | IllegalAccessException e) {
                                throw new InternalError(e);
                            }
                        }
                    });
        }
    View Code

         咱们主要看这一句:ClassDefiner.defineClass(xx, declaringClass.getClassLoader()).newInstance();

         在ClassDefiner.defineClass方法实现中,每被调用一次都会生成一个DelegatingClassLoader类加载器对象 ,这里每次都生成新的类加载器,是为了性能考虑,在某些情况下可以卸载这些生成的类,因为类的卸载是只有在类加载器可以被回收的情况下才会被回收的,如果用了原来的类加载器,那可能导致这些新创建的类一直无法被卸载!

         而反射生成的类,有时候可能用了就可以卸载了,所以使用其独立的类加载器,从而使得更容易控制反射类的生命周期!

    最后,用几句话总结反射的实现原理:

        1. 反射类及反射方法的获取,都是通过从列表中搜寻查找匹配的方法,所以查找性能会随类的大小方法多少而变化;

        2. 每个类都会有一个与之对应的Class实例,从而每个类都可以获取method反射方法,并作用到其他实例身上;

        3. 反射也是考虑了线程安全的,放心使用;

        4. 反射使用软引用relectionData缓存class信息,避免每次重新从jvm获取带来的开销;

        5. 反射调用多次生成新代理Accessor, 而通过字节码生存的则考虑了卸载功能,所以会使用独立的类加载器;

        6. 当找到需要的方法,都会copy一份出来,而不是使用原来的实例,从而保证数据隔离;

        7. 调度反射方法,最终是由jvm执行invoke0()执行;

    转载于:https://www.cnblogs.com/yougewe/p/10125073.html

    展开全文
  • 具有优先级管理功能的任务队列管理器 缝合多个原文件后编码输出成一个单一的文件 同时生成多个目标格式文件 长宽比转换 NTSC和PAL制式之间相互转换 帧速率插值计算和转换 时间码创建和保留 新 自适应去交错 ...
  • 具有优先级管理功能的任务队列管理器 缝合多个原文件后编码输出成一个单一的文件 同时生成多个目标格式文件 长宽比转换 NTSC和PAL制式之间相互转换 帧速率插值计算和转换 时间码创建和保留 新 自适应去交错 ...
  • 163. Iub和Iur接口流量计算方法 128 164. 各种天馈分布系统比较,适用环境 129 165. 2G对3G会不会有干扰?3G对2G会不会有干扰? 130 166. 市区室内覆盖解决方案主要有哪些 130 167. 核心网如何从R99向R4平滑...
  • 微软英库拼音输入法是一款多功能的拼音输入法软件。 创新中文引擎:30 多万词条的中文词库和新词热词,中英文混合一次输入,自学习  V 模式:直接在输入法内搜索图片、地图或网页,由必应搜索驱动  多媒体输入...
  • 并确保在同一事务处理种对相同数据两次查询看到是相同值。 值范围: TRUE | FALSE 默认值: FALSE row_locking: 说明: 指定在表已更新或正在更新时是否获取行锁。如果设置为 ALWAYS, 只有在表被更新后才获取...
  • 建立宽带连接的方法请点查看宽带连接方法 。 用户名称:这里填你所选择宽带连接名称所对应该的ADSL/LAN等的用户名,也就是ISP商提供的宽带连接账号。 用户密码:这里填上面所埴的用户名称对应该的密码,这个也是ISP...
  • 千里马酒店前台管理系统V7使用手册

    热门讨论 2011-06-16 14:09:38
    三层逻辑结构好处是提高了系统性能、安全、可扩充,使得系统为酒店带来更好使用效果和效益。 2.2 功能特色 千里马酒店前台管理系统V7.2具有先进理念、严谨设计、全面的功能、优异性能、非常...
  • asp.net知识库

    2015-06-18 08:45:45
    可按任意字段排序的分页存储过程(不用临时的方法,不看全文会后悔) 常用sql存储过程集锦 存储过程中实现类似split功能(charindex) 通过查询系统表得到纵向的表结构 将数据库表中的数据生成Insert脚本的存储过程!!! ...
  • 3. 重新组织函数

    2015-03-29 10:13:49
    重构,无外乎就是重新组织变量(实例变量,静态变量,局部变量,临时变量),表达式,函数,类,继承机制(extends, implements)等,以提高代码可读性,可维护等。代码世界里不希望看到高富帅,一切都以“小”...
  • 兼顾深度与广度,不仅对实际问题现象、产生原因和相关原理进行了深入浅出讲解,更主要是,结合实际应用环境,提供了一系列解决问题思路和方法,包括详细操作步骤,具有很强实战和可操作。...
  •  ◇ 用户操作手册:本手册详细描述软件的功能、性能和用户界面,使用户对如何使用该软件得到具体了解,为操作人员提供该软件各种运行情况有关知识,特别是操作方法的具体细节。  ◇ 测试计划:为做好集成测试...
  • 的方法: · 实体型:用矩形表示,矩形框内写明实体名; · 属性:用椭圆形表示,并 用无向边将其与相应的实体连接起来; · 联系:用菱形表示,菱形框内写明联系名,并用 无向边分别与有关实体连接起来,同时在...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 124
精华内容 49
关键字:

临时提高性功能的方法