面试题多态,JDK源码阅读

作者: 新金沙平台  发布:2019-08-09

JDK源码阅读(1)_简介 java.io,jdkjava.io

1.简介

  针对这一个版块,主要做一个java8的源码阅读笔记。会对一些在javaWeb中应用比较广泛的java包进行精读,附上注释。对于容易混淆的知识点给出相应的对比分析。
  精读的源码顺序主要如下:

(1)第一部分:这部分是java开发的最常见包和类,要求精读:
  • java.io
  • java.lang
  • java.util

 

 (2)第二部分:这一有个别是java web开拓的主题内容之一,要求要有深厚的敞亮。(包涵了java的反光、网络io、非阻塞、并发编制程序)————有些大牌说,这一片段行使的三六九等,精晓的品位高低,会决定二个java开拓程员的水平:

 

  • java.lang.reflect
  • java.net
  • javax.net.*
  • java.nio
  • java.util.concurrent.*

 

  (3)第三部分:这一部分须要不高,实行简易泛读,能看懂、会用就能够:

 

  • java,lang.annotation
  • javax.annotation
  • java.lang.ref
  • java.math
  • java.rmi.*
  • javax.rmi.*
  • java.security.*
  • javax.security.*
  • java.sql
  • javax.sql.*
  • javax.transaction.*
  • java.test
  • java.xml.*
  • org.w3c.dom.*
  • org.xml.sax.*
  • javax.crypto.*
  • javax.imageio.*
  • javax.jws.*
  • java.util.jar
  • java.util.logging
  • java.util.prefs
  • java.util.regex
  • java.util.zip

 

2.源码阅读:—— day1:(java.io_BufferedInputStream类)

(1)java.io——BufferedInputStream类

package java.io;
// java.io包,通过数据流、序列化和文件系统提供系统输入和输出
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
// 导入一个包,这个包运用到了一个多线程的原子更新器

  public class BufferedInputStream extends FilterInputStream {
    // 继承fileinputstream,为输入流添加一些功能;使用他防止每次读取时都得进行实际写操作;代表“使用缓冲区”

    private static int DEFAULT_BUFFER_SIZE = 8192;
  // 该变量定义了默认的缓冲大小 为8192;

    private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
  // 最大长度依然是Integer.MAX_VALUE,并不是Integer.MAX_VALUE-8

    protected volatile byte buf[];
  // 存储数据的内部缓冲区数组,必要的时候可以用另外一个大小不同的数组替换它;
  // 注意volatile关键字表示不稳定变量,每次线程存取都应该直接从主程序中读取
  // (作用于多线程环境中)防止主程序值改变,影响其中某个线程的值无法匹配对应而出错;

    private static final
        AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
        AtomicReferenceFieldUpdater.newUpdater
        (BufferedInputStream.class,  byte[].class, "buf");   
   // 缓存数组的一个原子更新器,该成员变量与buf数组的volatile关键字一起,实现buf数组的原子的更新;

    protected int count;
   // 比缓冲区中最后一个有效字节的索引大 1 的索引。此值始终处于 0 到 buf.length 的范围内;
   // 从 buf[0] 到 buf[count-1] 的元素包含从底层输入流中获取的缓冲输入数据。


    protected int pos;
  // pos = position ,缓冲区中的当前位置,这是将从buf数组中读取的下一个字符的索引;
  // 此值始终处于 0 到 count 的范围内。如果此值小于 count,则 buf[pos] 将作为下一个输入字节;
  // 如果此值等于 count,则下一次 read 或 skip 操作需要从包含的输入流中读取更多的字节。
  

    protected int markpos = -1;
  // 最后一次调用 mark 方法时 pos 字段的值为 -1; markpos的值始终处于 -1 到 pos 的范围内,
  // 如果输入流中没有被标记的位置,则此字段为 -1;如果输入流中有被标记的位置,则 buf[markpos] 将用作 reset 
  // 操作后的第一个输入字节。如果 markpos 不是 -1,则从位置 buf[markpos] 到 buf[pos-1] 之间的
  // 所有字节都必须保留在缓冲区数组中(尽管对 count、pos 和 markpos 的值进行适当调整后,这些字节可能移动到
  // 缓冲区数组中的其他位置);除非 pos 与 markpos 的差超过 marklimit,否则不能将其丢弃。


    protected int marklimit;
  // 调用 mark 方法后,在后续调用 reset 方法失败之前所允许的最大提前读取量。
  // 只要 pos 与 markpos 之差超过 marklimit,就可以通过将 markpos 设置为 -1 来删除该标记。

    private InputStream getInIfOpen() throws IOException {
        InputStream input = in;
        if (input == null)
            throw new IOException("Stream closed");
        return input;
    }
  // 如果输入流为 null ,则抛出传输流关闭“stream closed”的异常
  // 如果输入流不为 null ,则返回输入流,并将数据存储于 input 中


    private byte[] getBufIfOpen() throws IOException {
        byte[] buffer = buf;
        if (buffer == null)
            throw new IOException("Stream closed");
        return buffer;
    }
  // 创建一个输入流数组,用来保存其参数;当输入保存的参数数组为 null 时,抛出“stream closed”异常,
  // 当不为 null 时,直接返回数组 buffer ,并把输入流存储在数组之中;


    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);           // java中,用this引用当前对象;
    }
  // 创建一个缓冲输入流 BufferedInputStream 并保存其数据,即输入流 in ,以便将来使用;
  // 回调缓冲输入流,并且保存其默认参数(缓冲输入流的长度);


    public BufferedInputStream(InputStream in, int size) {
        super(in);  // java类中使用super引用父类成分,InputStream是BufferedInputSream的父类;
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");

        buf = new byte[size];
    }
  // 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,
  // 以便将来使用。创建一个长度为 size 的内部缓冲区数组并将其存储在 buf 中。


    private void fill() throws IOException {
        byte[] buffer = getBufIfOpen();
        if (markpos < 0)
            pos = 0;                        // 没有标记,总是指向缓冲流的初始位置;
        else if (pos >= buffer.length)      // 位置比缓冲区长度大,缓冲区中没有空间了;
            if (markpos > 0) {              // 抛出缓冲区的前半部分;
                int sz = pos - markpos;     // 字符串数据的长度;
                System.arraycopy(buffer, markpos, buffer, 0, sz);
                pos = sz;
                markpos = 0;                // 进行复制和初始化 pos 和 markpos;
            } else if (buffer.length >= marklimit) {
                markpos = -1;                // 缓冲区太大了,是一个无效的标志位,返回-1;
                pos = 0;                     // 降低缓冲区的内容;
            } else if (buffer.length >= MAX_BUFFER_SIZE) {
                throw new OutOfMemoryError("Required array size too large");
            } else {                        // 缓冲区进行拓展
                int nsz = (pos <= MAX_BUFFER_SIZE - pos) ?
                        pos * 2 : MAX_BUFFER_SIZE;
                if (nsz > marklimit)
                    nsz = marklimit;
                byte nbuf[] = new byte[nsz];
                System.arraycopy(buffer, 0, nbuf, 0, pos);
                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                    // 如果这里是不同步的关闭,则不能进行替换; 
                    // 注意:如果满了则需要进行拓展变换
                    // 对于多线程来说,永远不能达到
                    // 唯一的方式是通过关闭来结束
                    // 插入 buf == null;
                    throw new IOException("Stream closed");
                }
                buffer = nbuf;
            }
        count = pos;
        int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
        if (n > 0)
            count = n   pos;    // 数量
    }



    public synchronized int read() throws IOException {
        if (pos >= count) {
            fill();           // 如果位置的值 pos 大于等于 长度数量 count;则调用fill()方法
            if (pos >= count)
                return -1;
        }
        return getBufIfOpen()[pos  ] & 0xff;
    }



    // 将字符串读入到数组 array 之中,如果需要,最多进行 1 次;
    private int read1(byte[] b, int off, int len) throws IOException {
        int avail = count - pos;
        if (avail <= 0) {
       // 如果请求的长度至少和缓冲器一样的大,并且没有进行 mark/reset 操作;
       // 不要急于拷贝不要急于拷贝字节到本地缓冲器之中,如果这样,缓冲流将会无害级联;
            if (len >= getBufIfOpen().length && markpos < 0) {
                return getInIfOpen().read(b, off, len);
            }
            fill();
            avail = count - pos;
            if (avail <= 0) return -1;
        }
        int cnt = (avail < len) ? avail : len;
        System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
        pos  = cnt;
        return cnt;
    }



    // 以所给的偏移量开始,从输入字节流中,读取到具体字节流数组中;
    public synchronized int read(byte b[], int off, int len)
        throws IOException
    {
        getBufIfOpen();   // 检查缓冲流是否关闭;
        if ((off | len | (off   len) | (b.length - (off   len))) < 0) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        int n = 0;
        for (;;) {
            int nread = read1(b, off   n, len - n);   // 读入
            if (nread <= 0)
                return (n == 0) ? nread : n;    // 简单的一个选择语句,当n==0返回nread,否则返回n;
            n  = nread;
            if (n >= len)
                return n;
            // 如果输入流没有关闭,但是,已经没有字节可用,则直接返回;
            InputStream input = in;
            if (input != null && input.available() <= 0)
                return n;
        }
    }




    public synchronized long skip(long n) throws IOException {   // n为跳过字节数;
        getBufIfOpen();    // 检查字符流是否关闭
        if (n <= 0) {
            return 0;
        }
        long avail = count - pos;    //确定可用长度

        if (avail <= 0) {
            // 如果没有设定标志位置,也没有保存在 buffer 缓冲器中;
            if (markpos <0)
                return getInIfOpen().skip(n);

            // 填满 buffer 缓冲器,用以保存字节,等待重新设置;
            fill();
            avail = count - pos;
            if (avail <= 0)
                return 0;
        }

        long skipped = (avail < n) ? avail : n;  // 选择判断语句,跳过 avail 长度,或者跳过 n 长度;
        pos  = skipped;
        return skipped;
    }



    //返回可以从该输入流中读取(或跳过)的字节数的估计数,而不需要对该输入流的方法的下一次调用进行阻塞。
    //下一个调用可能是同一个线程或另一个线程。此多字节的单个读或跳过不会阻塞,但可能读取或跳过更少字节。
    public synchronized int available() throws IOException {
        int n = count - pos;
        int avail = getInIfOpen().available();
        return n > (Integer.MAX_VALUE - avail)
                    ? Integer.MAX_VALUE
                    : n   avail;
    }


    public synchronized void mark(int readlimit) {
        marklimit = readlimit;
        markpos = pos;
    }


      // reset()重置方法;
    public synchronized void reset() throws IOException {
        getBufIfOpen();     // 如果缓冲流关闭会抛出异常;
        if (markpos < 0)    // 标志位置小于 0 ,会抛出异常;
            throw new IOException("Resetting to invalid mark");
        pos = markpos;
    }



    public boolean markSupported() {
        return true;    // 测试该输入流支持位置标志;
    }

    // 关闭此输入流并释放与流相关联的任何系统资源;
    // 一旦流已经关闭,进一步read(),available(),reset(),或skip()调用会抛出IOException;
   // 关闭先前关闭的流没有效果。
    public void close() throws IOException {
        byte[] buffer;
        while ( (buffer = buf) != null) {
            if (bufUpdater.compareAndSet(this, buffer, null)) {
                InputStream input = in;
                in = null;
                if (input != null)
                    input.close();
                return;
            }
           //其他的情况下,一个新的缓冲区被重新装入,调用fill()方法;
        }
    }
}

   这一路还算相比较轻易,看看api也基本上,一时间可能应当看看源码,会知其之所以然~

java.io,jdkjava.io 1.简单介绍针对那贰个版块,首要做二个java8的源码阅读笔记。会对有些在javaWeb中央银行使比较宽泛的java包...

(一道面课题)关于多态,面试题多态

一.贯彻多态所具备的法规有3个:

1.承袭关系

2.子类重写父类的秘诀

3.父类的引用指向子类的靶子

二.贯彻一波:

1.编写Animal类,作为三个父类,有贰个name方法,用于给子类重写.

public class Animal {
   public void name(){
    System.out.println("我是一只动物");
   }
}

2.编辑Monkey类承袭Animal类,同等对待写父类name方法,具有自身独有的climb()方法

public class Monkey extends Animal { 
 @Override
 public void name() {
  System.out.println("我是一只猴子");
 }
 public void climb()
 {
  System.out.println("我会爬树");
 }

}

3.编纂测量试验类

1.先上一张图,他表达的三个道理是:父类的引用指向子类的靶亥时,父类只可以访问自身所负有的法子,

例如说Monkey类的climb()方法.animal是不能够访谈的.

图片 1

2.上全体代码:

public class PolymorphismDemo {
     public static void main(String[] args) {
     //向上转型,父类的引用指向子类的对象
  Animal animal=new Monkey();
  animal.name();
 }
}

3.结果:

图片 2

4.总计,画张图吧~~动态绑定,在运作时期明确目的,然后运转对应的办法

图片 3

 

一.完结多态所具备的法规有3个: 1.接续关系 2.子类重写父类的艺术 3.父类的援引指向子类的对象...

java 导入Excel,java导入excel

一、思路解析

  1、大家要做导入,实际上约等于先文件上传,然后读取文件的数量。

  2、大家要有三个导入的模版,因为我们导入的Excel列要和大家的多寡字段相配上,所以大家要给它来三个规定,也等于模板。

  3、根据大家同盟社的覆辙,是做了多个导入音讯的有的时候表,用来存导入文件中的音讯。每当导入的时候,大家先把表消息清空,再得到数量放进来,然后大家对导入的数目开始展览检查,最终才全部导入。

    那样做的目标是幸免导入的数目和列未有对上却也直接导到了库里面,要真那样了就很难堪。大家做了八个按键,三个导入,二个认可导入,贰个导入模板下载。

  4、捋一下经过:

    点击批量导入按键,跳转到导入页面。

    点击模板下载。(事先写好一个模板.xls文件,此按键放置下载链接)

    在模板中录入数据。

    点击导入按键,跳出文件上传模态框。

    采纳文件,上传文件。

    上传成功后调用后台方法,读取文件内容。

    把内容退换表格,展现到导入页面。

    观望数占有未有失误。

    点击确认导入,调用后台方法,实行导入操作。

    回调函数,导入成功/导入失败 的唤起。

二、代码剖析

   1、前端js代码:

 1 var actionPath = contextPath   "/alumni-import";
 2 
 3 $(function() {
 4     //加载数据
 5     loadData();
 6     //上传文件
 7     uploadFile({
 8         subfix: ['xls'],
 9         subfixTip: "请选择Excel的xls文件!",
10         successCall: function(data, status, a) {
11             $('[name=attachementPath]').val(data.fileName);
12             $.post(actionPath   "!importExcel", { "f_id": data.f_id }, function(data) {
13                 if (data.success) {
14                     alertify.alert(data.message);
15                     $("#myModal-import").modal("hide");
16                     loadData();
17                 } else {
18                     alertify.alert(data.message);
19                 }
20 
21             }, "json");
22         }
23     });
24     //导入
25     $("#btn-import").click(function() {
26         var html = template("importTpl");
27         $("#import-body").html(html);
28         $("#myModal-import").modal();
29     });
30     //确认导入
31     $("#btn-sure").click(function() {
32         var type = $("#indentity-type").val();
33         alertify.confirm("确定要全部导入吗?", function(e) {
34             if (!e) { return; } else {
35                 $.post("/alumni-import!saveReal?type="   type, function(data) {
36                     alertify.alert("导入成功!", function() {
37                         location.href = "/alumni!hrefPage";
38                     });
39                 }, "json");
40             }
41         });
42     });
43 });50 
51 function loadData() {
52     var options = {
53         url: actionPath   "!page"
54     };
55     loadPaginationData(options);
56 }

  2、后台效用代码

    前端有多个央求,一个初阶化页面数据加载,当然,一早先是不曾数量的;三个导入文本上传;二个承认导入;叁个导入达成后页面跳转回要音讯页面(音讯页面有八个批量导入跳转到那的导入页面)。

    首个后末了叁个就不讲了。讲一下一次之个和第五个。

    ①第二个

 1     //上传文件后调用
 2     public void importExcel() {
 3         try {
 4             //清空临时表的数据
 5             baseAlumniImportSrv.deleteAll();
 6             //读取文件
 7             File file = gridFsDao.readFile(f_id);
 8             //把文件信息给临时表
 9             int count = excelXYSrv.importExcel(file);
10             //清空上传的文件
11             file.delete();
12             sendSuccessMsg(count, "上传成功"   count   "条数据");
13         } catch (IOException e) {
14             LOGGER.error(e);
15             sendFailMsg(null, "上传失败");
16         }
17     }

 1     @Override    //使用MongoDB GridFS,具体详解请各自初学者自行百度,注释写不下去了,我也不会,心态爆炸~~~
 2     public File readFile(String f_id) {
 3         //拿到文件
 4         GridFSDBFile gridFSFile = mongoGridFs.findOne(new Query(Criteria.where(F_ID).is(f_id)));
 5         if (gridFSFile == null) {
 6             return null;
 7         }
 8         String fileName = gridFSFile.getFilename();
 9         String extension = fileName.substring(fileName.lastIndexOf("."), fileName.length());
10         InputStream ins = gridFSFile.getInputStream();
11         String tmpFile = UUID.randomUUID().toString()   extension;
12         File file = new File(tmpFile);
13      
14         try {
15             OutputStream os = new FileOutputStream(file);
16             int bytesRead = 0;
17             byte[] buffer = new byte[8192];
18             while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
19                 os.write(buffer, 0, bytesRead);
20             }
21             os.close();
22             ins.close();
23         } catch (IOException e) {
24             e.printStackTrace();
25         }
26 
27         return file;
28 
29     }

 1     /**
 2      * @param excelFile
 3      *            从excel中读取数据,并存储到数据库临时表中
 4      * @return
 5      * @throws IOException
 6      */
 7     @Override
 8     public int importExcel(File excelFile) throws IOException {
 9         List<List<Object>> datas = ExcelImportUtil.readExcel(excelFile);
10         int count = 0;
11         for (int i = 1; i < datas.size(); i  ) {
12             BaseAlumniImport entity = this.convert2Entity(datas.get(i));
13             this.baseAlumniImportSrv.save(entity);
14             count  ;
15         }
16         return count;
17     }

  ②第三个

 1     public void saveReal() {
 2         int count = 0;
 3         List<BaseAlumniImport> importList = this.baseAlumniImportSrv.findAll();
 4         for (int i = 0; i < importList.size(); i  = 10) {
 5             List<BaseAlumniImport> newlist = new ArrayList<>();
 6             if ((i   10) < importList.size()) {
 7                 newlist = importList.subList(i, i   10);
 8             } else {
 9                 newlist = importList.subList(i, importList.size());
10             }
11             count  = excelXYSrv.saveReal(newlist, this.type);
12         }
13         sendSuccessMsg(count, "导入成功"   importList.size()   "条数据");
14     }

 1     @Override
 2     public int saveReal(List<BaseAlumniImport> importList, String type) {
 3         int count = 0;
 4         String alumniIdentityName = dicSrv.findById(DicAlumniIdentity.class, Integer.parseInt(type)).getValue();
 5         for (BaseAlumniImport inst : importList) {
 6             LOGGER.info(inst.getId());
 7             BaseAlumni v = this.importExportSrv.convert(inst);
 8             v.setId(IdKit.uuid());
 9             v.setCreateTime(new Date());
10             v.setLastUpdate(new Date());
11             this.baseAlumnidDao.save(v);
12             this.baseAlumniImportSrv.deleteById(inst.getId());
13             count  ;
14         }
15         return count;
16     }

 1     @Override
 2     public int saveReal(List<BaseAlumniImport> importList, String type) {
 3         int count = 0;
 4         String alumniIdentityName = dicSrv.findById(DicAlumniIdentity.class, Integer.parseInt(type)).getValue();
 5         for (BaseAlumniImport inst : importList) {
 6             LOGGER.info(inst.getId());
 7             BaseAlumni v = this.importExportSrv.convert(inst);
 8             v.setId(IdKit.uuid());
 9             v.setCreateTime(new Date());
10             v.setLastUpdate(new Date());
11             this.baseAlumnidDao.save(v);
12             this.baseAlumniImportSrv.deleteById(inst.getId());
13             count  ;
14         }
15         return count;
16     }

    没啥好讲的……会的相应都能看懂,看不懂的笔者也不会……

三、结果图

  图片 4

  图片 5

 

  图片 6

   图片 7

 

 

 

 导入成功~

 

 

 

    

 

导入Excel,java导入excel 一、思路深入分析1、我们要做导入,实际上也便是先文件上传,然后读取文件的数据。 2、大家要有一个导入的模板...

本文由新金沙平台发布于新金沙平台,转载请注明出处:面试题多态,JDK源码阅读

关键词: 新金沙平台

上一篇:后端开挂,p名称空间注入属性
下一篇:没有了