• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
Lith
博客园    首页    新随笔    联系   管理    订阅  订阅
Java学习笔记(二) - Java进阶语法
参考书目:Java核心技术 卷II

目录

  • 目录
  • 流库
    • 流
    • 约简
      • Optional类型
      • 收集结果
      • 约简
    • 基本流
      • 基本类型流
      • 并行流
  • I/O
    • 输入输出流
    • 文件
    • 正则表达式
  • XML
    • XML文档
  • 网络
    • 连接服务器
    • 实现服务器
    • URI
    • HTTP
  • 数据库
    • JDBC
    • 元数据
    • 事务
    • JDBC数据源和连接池
  • 日期和时间
    • 本地日期
    • 时区时间
  • 国际化
    • Locale
    • 资源包
  • 脚本/编译/注解
    • 脚本
    • 编译
    • 注解
      • 标准注解
  • 安全
    • 数字签名
    • 加密

流库

流

  • 流与集合:
    • 流不存储元素
    • 流的操作不会修改其数据源
    • 流的操作是惰性的(需要结果时才会执行)
    • 产生集合中的元素流
      • 顺序流:words.stream()
      • 并行流:words.parallelStream()
  • 流的创建:
    • 将集合转换为流:Stream<T> w = Stream.of(... ...)
    • 用数组的一部分元素创建一个流:Array.stream(array,from,to)
    • 空流:Stream<String> w = Stream.empty()
    • 无限流:
      • 常量流:Stream<String> echos = Stream.generate(() -> "Echo")
      • 序列流:Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO,n -> n.add(BigInteger.ONE));
    • 有限序列流:Stream<BigInteger> integers = Stream.iterate(BigInteger.ZERO,n -> n.compareTo(limit) < 0,n -> n.add(BigInteger.ONE));
    • 短流:Stream.ofNullable(...) 用对象创建一个长度为1的流
  • filter:
    • filter(Predicate<T>)
  • map:将函数应用到每个元素上(也可以使用forEach)
    • map(s -> s.substring(0,1));
  • flatmap:
    • codePoints("boat")返回值是流["b","o","a","t"]
    • 包含流的流:Stream<Stream<String>> result = words.stream().map(w -> codePoints(w))
    • 摊平为单个流:Stream<String> flatResult = words.stream().flatMap(w -> codePoints(w))
  • 子流/组合流:
    • stream.limit(n) n个元素的子流
    • stream.skip(n) 丢弃前n个元素的子流
    • 条件为真/假时获取元素:stream.takeWhile(predicate) / stream.dropWhile(predicate)
    • 组合流:Stream.contact(stream1,stream2)
  • 其它流:
    • stream.distinct() 剔除重复元素
    • stream.sorted(Comparator.comparing(String::length).reversed()) 流排序
    • stream.peek(...) 每次获取元素时,调用一次函数

约简

  • 简单约简:
    • stream.count()
    • stream.max(String::compareToIgnoreCase) 返回Optional< T >

Optional类型

  • Optional:包装器对象,包装了类型T的对象或null
  • 获取Optional:不存在任何值的情况下产生替代值
    • optional.orElse(......)
    • optional.orElseGet(() -> ......)
    • optional.orElseThrow(IllegalStateException::new)
  • 消费Optional:
    • optional.ifPresent(v -> Process v) 值存在,则被传递给函数
    • optional.ifPresentOrElse( v -> ProcessTrue v , v -> ProcessFalse v)
  • 管道化Optional:
    • Optional<T> opt = optional.map(v -> Process v)
    • Optional<T> opt = optional.filter(Predicate)
    • 可替代Optional:Optional<T> opt = optional.or(Supplier)
  • 创建Optional:
    • Optional.empty()
    • Optional.of(...)
  • flatMap构建Optional:若s的方法f返回Optional<T>,类型T具有返回Optional<U>的方法
    • 不能调用s.f().g()
    • 组合:s.f().flatMap(T::g)
  • Optional转换为流:
    • 将Optional对象转换为具有0个或1个元素的流:optional.stream()

收集结果

  • 创建泛型数组: stream.toArray(String[]::new)
  • Collectors类:
    • 列表: List<String> result = stream.collect(Collectors.toList());
    • 集: Set<String> result = stream.collect(Collectors.toSet());
      • TreeSet<String> result = stream.collect(Collectors.toCollection(TreeSet::new));
    • 字符串: String result = stream.collect(Collectors.joining());
    • 约简结果: Collectors.summarizing(Int|Long|Double)(...函数...) 返回 (Int|Long|Double)SummaryStatistics
  • 收集到映射表:
    • Collectors.toMap(Person::getId,Person::getName)
  • 群组和分区:
    • Map<String,List<Locale>> countryToLocales = locales.collect(Collectors.groupingBy(Locale::getCountry));
    • Locale::getCountry是群组的分类函数
    • 下游收集器:
      • 集:Map<String,Set<Locale>> countryToLocaleSet = locales.collect(groupingBy(Locale::getCountry,Collectors.toSet()));
      • 数字:counting、summing(Int|Long|Double)、maxBy、minBy、collectingAndThen、mapping

约简

  • reduce(...二元函数...)
//从前两个元素开始持续应用
List<Integer> values = ...;
Optional<Integer> sum = values.stream().reduce((x,y) -> x + y);
//幺元值:计算起点
Integer sum = values.stream().reduce(0,(x,y) -> x + y);

基本流

基本类型流

  • IntStream/DoubleStream:
    IntStream stream = IntStream.of(1,1,2,3,5);
    //values --- int[]
    IntStream stream = Arrays.stream(values,from,to)
    
    • IntStream.generate/IntStream.iterate
    • IntStream.range(0,100)/IntStream.rangeClosed(0,100)
  • 对象流转换:mapToInt、mapToLong、mapToDouble
    Stream<String> words = ...;
    IntStream lengths = words.mapToInt(String::length);
    
  • 基本类型流转换:IntStream.boxed()

并行流

  • 获取并行流:Stream<String> parallel = words.parallelStream(); 集合->并行流
  • 转化并行流:Stream<String> parallel = wstream.parallel(); 顺序流->并行流
  • 无排序处理:stream.unordered()

I/O

输入输出流

  • 读写字节
    • java.io.InputStream
    • java.io.OutputStream
  • 输入输出流家族:
    • 读写字节:InputStream/OutputStream
    • 读写Unicode码元:Reader/Writer
  • 组合输入/输出流过滤器:
    • 文件输入输出流:FileInputStream/FileOutputStream
      • FileInputStream fin = new FileInputStream("employee.dat")
    • 构造器:
      • 将字节组装到数据类型:DataInputStream din = new DataInputStream(fin)
      • 使用缓冲机制:new BufferedInputStream(fin)
      • 预览字节(可回推流):new PushbackInputStream(fin)
  • 文本输入与输出:(java虚拟机中统一以Unicode编码,输入输出需要进行转换)
    • OutputStreamWriter/InputStreamReader:Unicode码元与字节流转换
    • 文件文本输出:PrintWriter out = new PrintWriter("employee.txt",StandardCharsets.UTF_8)
      • 输出:out.print()/println()/printf()
    • 文件文本输入:
      • Scanner类:Scanner in = new Scanner(......)
        • 读入Int:in.nextInt()
      • 文本读入字符串:String content = Files.read(String path,charset)
      • 按行读入:List<String> lines = Files.readAllLines(path,charset)
        • String line = in.nextLine();
        • String[] tokens = line.split("\\|")
      • 流对象(大文件):Stream<String> lines = Files.lines(path,charset)
      • 扫描器(分隔符):in.useDelimiter("\\PL+"); --- 读入分隔符分隔的字符串(符号)
        • 读入下一个符号:String word = in.next()
        • 获取包含所有符号的流: Stream<String> words = in.tokens();
  • 读写二进制:
    • DataInput/DataOutput接口:以二进制格式读写数据类型
      • read/write(Float|Double|Int|Char|Short|Boolean|Long|UTF)
      • writeChars/writeByte
      • DataInputStream/DataOutputStream类实现了对应接口
    • 随机访问文件(在文件中任何位置查找或写入数据)
      • RandomAccessFile类(实现了DataInput/DataOutput接口)
      //读入访问
      RandomAccessFile in = new RandomAccessFile("emlpoyee.dat",r);
      //读写访问
      RandomAccessFile in = new RandomAccessFile("emlpoyee.dat",rw);
      
      • getFilePointer方法返回文件指针位置
      • in.seek(...)设置文件指针位置
    • ZIP
      • ZipInputStream(getNextEntry返回文档中的项-ZipEntry类型)
      • ZipOutputStream(putNextEntry写文件)
  • 对象输入/输出流与序列化:
    • 对象序列化
      • 打开ObjectOutputStream对象
        • ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("employee.dat"));
      • 保存对象
        • out.writeObject(...对象实例...);
      • 打开ObjectInputStream对象
        • ObjectInputStream in = new ObjectInputStream(new FileInputStream("employee.dat"));
      • 以对象被写出时的顺序获得
        • Employee e = (Employee) in.readObject();
      • 序列化类应声明Serializable接口(该接口没有任何方法需要实现)

文件

  • Path:
    • Path p = Paths.get("/home","harry","user.properties");
    • p.resolve(q)
      • q为绝对路径,结果就是q
      • 否则,将p/q作为结果
    • toAbsolutePath方法产生给定路径的绝对路径
  • 读写文件:
    • 读取文本内容:String content = Files.readString(path,charset)
    • 行读取:List<String> lines = Files.readAllLines(path,charset)
    • 写入文本内容:Files.writeString(path,content.charset);
    • 追加内容:Files.write(path,content.getBytes(charset),StandardOpenOption.APPEND);
    • 写入行集合:Files.write(path,lines,charset);
    • 读写大文件:Files.newInputStream(path)/Files.newOutputStream(path)处理
  • 创建文件目录:
    • 创建新目录:Files.createDirectory(path)/Files.createDirectories(path)
    • 创建空文件:Files.createFile(path)
  • 复制/移动/删除文件:
    • 复制:Files.copy(fromPath,toPath)
    • 移动:Files.move(fromPath,toPath)
    • 输入流:Files.copy(inputStream,toPath)/Files.copy(fromPath,outputStream)
    • 删除:Files.delete(path)
  • 获取文件信息:
    • exists/isHidden/isReadable/isWritable/isExecutable/isRegularFile/isDirectory/isSymbolicLink/size/getowner
  • 目录:
    • Files.list(...)方法返回目录中各项的Stream< Path >对象(不会进入子目录)
    • Files.walk(...)与list方法类似,但会进入各子目录
    • 访问目录中的所有成员:Files.walkFileTree(Path.get("/"),new FileVistor<Path>() {......});
  • ZIP文件系统:
    • 建立文件系统:FileSystem fs = FileSystem.newFileSystem(Paths.get(zipname),null);
    • 从ZIP文档中复制文件:Files.copy(fs.getPath(sourceName),targetPath);
  • 内存映射文件:
    • 高速存取文件
    • 文件通道:FileChannel channel = FileChannel.open(path,options)
    • 获得ByteBuffer缓冲区:MappedByteBuffer buffer = channel.map(FileChannel.MapMode.Read_ONLY,0,length)
      • FileChannel.MapMode.READ_ONLY 只读缓冲区
      • FileChannel.MapMode.READ_WRITE 读写缓冲区
      • FileChannel.MapMode.PRIVATE 对缓冲区的修改不会传播到文件中
    • buffer.get()方法读取/buffer.put()方法写入
  • 文件加锁机制:
    • 锁定文件:
      • channel = FileChannel.open(path);
      • 阻塞直至获得锁FileLock lock = channel.lock();
      • 阻塞则立即返回FileLock lock = channel.trylock();
    • 释放锁定:
      • try (FileLock lock = channel.lock()) { ...... }

正则表达式

  • 正则表达式:定位匹配特定模式的字符串
  • 语法:[Jj]ava.+
    • 第一个字母是J或j
    • 接下来三个字母是ava
    • 字符串的其余部分由一个或多个任意字符组成
  • 常用结构:
    • 字符类:[Jj],[0-9],[A-Za-z],[^0-9]
      • "-"表示范围,"^"表示补集
    • \:转义字符
    • ^和$匹配一行的开头和结尾
    • X和Y为正则表达式:XY表示任何X的匹配后跟随Y的匹配,X|Y表示X或Y的匹配
    • 表达式量词X+或X*:一个或多个X,0个或多个X
    • 群组匹配:( )
  • 匹配字符串:
    • 使用正则表达式构建Pattern
      • Pattern pattern = Pattern.compile(patternString);
    • 获得Matcher
      • Matcher matcher = pattern.matcher(input);
    • 调用
      • if (matcher.matches()) ...
    • 群组
      • matcher.group(index)
      • matcher.start(groupname)/matcher.end(groupname)/matcher.group(groupname)
    • input可以是任何实现了CharSequence接口的对象:String,StringBuilder,CharBuffer等
    • 流中匹配元素:Stream<String> result = stream.filter(pattern.asPredicate());
  • 多个匹配:
    //获取Stream<MatchResult>
    List<String> matches = pattern.matcher(input)
      .result()
      .map(Matcher::group)
      .collect(Collectors.toList());
    
  • 分隔符:
    • String[] tokens = input.split("\\s*,\\s*");
  • 替换匹配:
    • 将正则表达式出现的所有地方都用字符串替换
    • String output = matcher.replaceAll("#");

XML

XML文档

  • XML规则:
    • 大小写敏感
    • 结束标签不能省略
    • 属性值必须用引号括起来
    • 所有属性必须都有属性值
  • 文档结构:
    • 文档头:<?xml version="1.0" ? > 或 <?xml version="1.0" encoding="UTF-8"?>
    • 文档类型:<!DOCTYPE ......>
    • 正文:根元素/其它元素 - 子元素
      • 元素可以包含属性,如:<size unit="pt">36</size>
      • 属性应用来指定值的解释
      • 字符引用:&#十进制,&#x十六进制
      • 实体引用:&lt,&gt,&amp,&quot,&apos代表小于、大于、&、省略号
      • 处理指令:如<?xml -stylesheet href="my.css" type="text/css"?>
      • 注释:<!-- This is a comment -->
  • 解析XML文档:
    • 读入:
      • 创建DocumentBuilder对象
      • DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      • DocumentBuilder builder = factory.newDocumentBuilder();
      • 从文件/URL/流中读入
      • File/URL/InputStream f = ......
      • Document doc = builder.parse(f)
      • 根元素
      • 获取根元素Element root = doc.getDocumentElement()
      • 获取元素标签String tag = doc.getTagName()
      • 子元素Node
      NodeList children = root.getChildNodes();
      for (int i = 0;i < children.getLength();i++)
      {
        Node child = children.item(i);
        //忽略空白元素
        if (child instanceof Element)
        {
          //对子元素下的子节点进行读取
          Element childElement = (Element) child;
          //获取第一个元素
          Text textNode = (Text) childElement.getFirstChild();
          String text = textNode.getData().trim();
          //.trim()能够把数据前后的空白字符删除
        }
      }
      
      //枚举节点属性
      NamedNodeMap attributes = element.getAttributes()
      Node attribute = attributes.item(i);
      String name = attribute.getNodeName();
      String value = attribute.getNodeValue();
      
  • 验证XML文档:
    • DTD文档类型定义
    <!DOCTYPE config [
      <!ELEMENT config ...>
      more rules
      ... ...
    ]>
    
    • 把DTD放在外部文档引用:<!DOCTYPE config SYSTEM "config.dtd">
    • 开启解析器验证:factory.setValidating(true);

网络

连接服务器

  • 打开Socket:Socket s = new Socket("time-a.nist.gov",13); 或 Socket s = new Socket()
  • 设置Socket连接:s.connect(new InetSocketAddress(host,post),timeout);
  • 输入流:InputStream inStream = s.getInputStream();
  • 输出流:OutputStream outStream = s.getOutputStream();
  • 套接字超时:s.setSoTimeout(10000);
    • 超时异常:SocketTimeoutException
  • 连接状态:s.isConnected()
  • 关闭状态:s.isClosed()
  • Internet地址:
    • 返回主机InetAddress对象:InetAddress address = InetAddress.getByName("time-a.nist.gov");
    • 访问IP地址字节:byte[] addressBytes = address.getAddress();
    • 多地址访问:InetAddress[] address = InetAddress.getAllByName(host);
    • 本地主机地址:InetAddress address = InetAddress.getLocalHost();

实现服务器

  • 服务器Socket:
    • 建立服务器:ServerSocket s = new ServerSocket(8180);
    • 建立服务器Socket:Socket incoming = s.accept();
    • 输入流:InputStream inStream = incoming.getInputStream();
    • 输出流:OutputStream outStream = incoming.getOutputStream();
    • 关闭SSocket:incoming.close()
  • 多客户端Socket:
    • ThreadedEchoHandler类:ThreadEchoHandler r = ThreadEchoHandler(incoming); Thread t = new Thread(r);
  • 半关闭:
    • 将输出流设置为流结束:socket.shutdownOutput()
    • 将输入流设置为流结束:socket.shutdownInput()
  • 可中断Socket:
    • 当线程发生中断,操作不会陷入阻塞,而是抛出异常
    • SocketChannel:SocketChannel channel = SocketChannel.open(new InetSocketAddress(host,port));
    • Scanner in = new Scanner(channel,StandardCharsets.UTF_8); 或 OutputStream outstream = Channels.newOutputStream(channel);

URI

  • URL/URI:
    • 构建URL:URL url = new URL(urlString);
    • 获取资源:InputStream inStream = url.openStream();
    • URI:统一资源标识符 [scheme:]schemeSpecificPart[#fragment]
      • 包含scheme:部分的称为绝对URI
      • schemeSpecificPart以/开头称为透明URI
      • schemeSpecificPart结构:[//authority][path][?query]
      • URL是特殊的URI,包含了定位定位Web资源的足够信息
    • URLConnection:
      • 获得Connection对象:URLConnection connection = url.openConnection();
      • 设置请求属性
        • HTTP请求头:connection.setRequestProperty(key,value[Base64]);
      • 连接远程资源:connection.connect();
      • 建立连接后可以查询头信息
        • HTTP响应头:
          • Stringkey = connection.getHeaderFieldKey(n);
          • String value = connection.getHeaderField(n);
          • Map<String,List<String>> headerFields = connection.getHeaderFields();
      • 访问资源:InputStream instream = connection.getInputStream();
  • 提交表单数据:
    • GET
      • http://host/path?query --- query为名字=值形式
      • San Francisco, CA --- San+Francisco%2c+CA(%2c是,的UTF-8码值)
      • &用作不同参数之间的连接符
    • POST
      • URL url = new URL("http://host/path");
      • URLConnection connection = url.openConnection();
      • 输出连接:connection.setOutput(true);
      • PrintWriter包装:PrintWriter out = new PrintWriter(connection.getOutputStream(),StandardCharsets.UTF_8);

HTTP

  • 获取客户端:
    • HttpClient client = HttpClient.newHttpClient();
    • 构建器模式
    HttpClient client = HttpClient.newBuilder()
      .followRedirects(HttpClient.Redirect.ALWAYS)
      .build();
    
  • Get请求:
    HttpRequest request = HttpRequest.newBuilder()
      .uri(new URI("http://horstmann.com"))
      .GET()
      .build();
    
  • POST请求:
    HttpRequest request = HttpRequest.newBuilder()
      .uri(new URI(url))
      .header("Content-Type", "application/json")
      //体发布器
      .POST(HttpRequest.BodyPublishers.ofString(jsonString))
      .build();
    
  • 响应处理:
    • 发送请求时,需规定客户端如何处理响应:
      • HttpResponse<String> reponse = client.send(request,HttpResponse.BodyHandlers.ofString());
    • 响应头:HttpHeaders responseHeaders = response.headers();
      • headers对象转化为map:Map<String,List<String>> headerMap = responseHeaders.map()
      • 获取特定键的第一个值:Optional<String> lastModified = headerMap.firstValue("......");
    • 状态码:int status = response.statusCode();
    • 异步响应
    //构建执行器
    ExecutorService executor = Executors.newCachedThreadPool();
    HttpClient client = HttpClient.newBuilder().executor(executor).build();
    //异步响应
    HttpRequest request = HttpRequest.newBuilder().uri(uri).GET().build();
    client.sendAsync(request,HttpResponse.BodyHandlers.ofString())
      .thenAccept(response -> ......);
    

数据库

JDBC

  • 加载数据库驱动:Class.forName("com.mysql.jdbc.Driver")
  • 数据库URL:URL --- jdbc:subprotocol:other stuff
  • 连接数据库:
    String url = "jdbc:postgresql:COREJAVA";
    String username = "dbuser";
    String password = "secret";
    Connection conn = DriverMannger.getConnection(url,username,password);
    
  • JDBC语句:
    • 执行SQL:
      • 创建Statement:Statement stat = conn.createStatement();
      • SQL语句字符串:String command = "...+...+...";
      • 执行SQL:stat.executeUpdate(command);
        • 执行SELECT语句应使用executeQuery()方法
        • 提交并获取结果集:ResultSet rs = stat.executeQuery(......);
    • SQL异常:
      • SQLException异常链
      • SQLWarning异常链
  • 查询数据库:
    • 预备语句:String Query = "...+...+..."; 使用?代替变量
    • 为变量指定值:stat.setString(int,String)
  • 可滚动结果集:
    • Statement:Statement stat = conn.createStatement(type,concurrency);
    • 预备语句:PreparedStatement stat = conn.prepareStatement(command,type,concurrency);
      • 设置参数:stat.setInt|Double|String|...(index,param)
    • 滚动:
      • 移动到下一行:rs.next()
      • 移动多行:rs.relative(n)
      • 移动到指定行号:rs.absolute(n)
      • 当前行行号:rs.getRow()
    • 获取当前行中列数据:
      • getArray/getString/getDouble/.............
      • 以列的索引作为参数:rs.getString(int colIndex)
      • 以列的名字作为参数:rs.getString(String colName)
      • 不知道获取列的数据类型,可一律采用getString方法
  • 可更新结果集:
    • Statement:Statement stat = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
    • UPDATE:rs.updateDouble("...",...); rs.updateRow();
    • INSERT:
    //移动至插入行
    rs.moveToInsertRow();
    rs.updateString("...",...);
    rs.insertRow();
    rs.moveToCurrentRow();
    
    • DELETE:rs.deleteRow();
  • 行集:不依赖数据库连接-javax.sql.rowset
    • 获取行集:
      • RowSetFactory factory = RowSetProvider.newFactory();
      • CachedRowSet crs = factory.createCachedRowSet();
    • 被缓存的行集:
      • ResultSet result = ......;
      • 结果集填充到行集:crs.populate(result);
      • 分页:crs.setPageSize(20); crs.nextPage();
      • 写数据库:crs.acceptChanges(conn);

元数据

  • 元数据:描述数据库及其组成部分的数据
    • DatabaseMetaData:DatabaseMetaData meta = conn.getMetaData();
    • 调用元数据:
      • 返回数据库表结果集:ResultSet mrs = meta.getTables(null,null,null,new String[] {"TABLE"});
      • 结果集的每一行包含了数据库中一张表的详细信息
    • ResultSetMetaData:ResultSetMetaData meta = rs.getMetaData();
      • 获取结果集的列数及每一列的名称、类型、字型宽度

事务

  • 事务:组合语句,确保所有语句都能顺利执行,否则回滚操作
  • 事务编程:
    • 关闭自动提交:conn.setAutoCommit(false);
    • 创建对象并提交:
      • Statement stat = conn.createStatement(); stat.executeUpdate(command);
      • conn.commit();
      • 出现错误,调用:conn.rollback();
  • 批量更新:
    • stat.addBatch(command);
    • 批量提交语句:int[] counts = stat.executeBatch();
  • 事务冲突:
    • 脏读(脏数据):一个事务访问数据并修改且并未提交,则另一个事务读取的数据称为脏数据,如果前一事务回滚,后一事务读取的数据是不正确的
    • 不可重复读:一个事务读取了一行数据,在事务结束前,另一事务访问了同一行并进行了修改,此时前一事务再次读取,结果会不同,称为不可重复读
    • 幻读:一个事务读取了满足条件的所有行后,另一个事务插入了一行数据,前一事务再次进行同样的条件读取时,结果多了一行数据,称为幻读
  • 事务隔离:
    • Read Uncommitted:保证读取过程不会读到非法数据,但无法避免事务冲突
    • Read Commited::保证一个事务不会读到另一个并行事务已修改但未提交的数据,避免了脏读
    • Repeatable Read:避免了脏读和不可重复读(即看不到其它事务对已有记录的更新/修改)
    • Serializable:最高级别事务隔离,串行化事务执行
  • 隔离级别:
    • conn.setTransactionIsolation(param)
      • TRANSACTION_NONE:不支持事务
      • TRANSACTION_READ_UNCOMMITTED:指定可以发生脏读、不可重复读和幻读
      • TRANSACTION_READ_COMMITTED:指定禁止脏读
      • TRANSACTION_REPEATABLE_READ:指定禁止脏读和不可重复读
      • TRANSACTION_SERIALIZABLE:指定禁止脏读、不可重复读和幻读

JDBC数据源和连接池

  • JDBC数据源:不需要在客户端程序中加载JDBC驱动(由容器加载) --- 连接对象的工厂
    • javax.naming.Context/java.sql.DataSource
    javax.naming.Context ctx = new javax.naming.InitialContext();
    javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup("java:comp/env/jdbc/bookstore");
    java.sql.Connection conn = ds.getConnection();
    ...
    conn.close();
    
    • javax.naming.Context接口表示一个命名上下文,定义了将对象和名字绑定以及通过名字查询对象的方法
    • java:comp/env是环境命名上下文,避免JNDI命名冲突
  • 连接池:连接对象为连接池中物理连接的一个句柄

日期和时间

  • 时间线:绝对时间
    • Instant start = Instant.now()
    • 表示时间线上的某个时间点
    • 时间差:Duration time = Duration.between(start,end);
    • 时间转换:long millis = time.toMillis();

本地日期

  • LocalDate:
    • LocalDate today = LocalDate.now();
    • LocalDate Birth = LocalDate.of(1903,6,14);
  • LocalTime:
    • LocalTime now = LocalTime.now();
    • LocalTime time = LocalTime.of(22,30,10);
    • LocalTime plustime = time.plusHours(8);

时区时间

  • ZonedDateTime:
    • ZonedDateTime skipped = ZonedDateTime.of(LocalDate.of(2013,3,31),LocalTime.of(2,30),ZoneID.of("Europe/Berlin"));
    • ZonedDateTime next = skipped.plus(Period.ofDays(7));
      -不能使用Duration.ofDays(7)
  • 时间格式化:
    • formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss);

国际化

Locale

  • Locale:Locale us_en = Locale.forLanguageTag("en-US");
    • 国别-语言 -> zh-CN
    • 预定义Locale:Locale.CHINA/Locale.SIMPLIFIED_CHINESE
  • 数字格式化:
    • Locale:Locale loc = Locale.GERMAN;
    • Format:NumberFormat fmt = NumberFormat.getCurrencyInstance(loc);
      • getNumberInstance --- 数字格式化
      • getCurrencyInstance --- 货币格式化
      • getPercentInstance --- 百分比格式化
    • 格式化:String result = fmt.format(123.45d);
    • 货币格式变更:fmt.setCurrency(Currency.getInstance("EUR"));
  • 日期格式化:
    • 格式器:
      • FormatStyle style = ...;
        • SHORT --- 7/16/69 --- 9:32 AM
        • MEDIUM --- Jul 16,1969 --- 9:32:00 AM
        • LONG --- July 16,1969 --- 9:32:00 AM EDT
        • FULL --- Wednesday,July 16,1969 --- 9:32:00 AM EDT
      • DateTimeFormatter dtFmt = DateTimeFormatter.ofLocalizedDataTime(style).withLocale(locale);
  • 排序和规范化:
    • 比较器:
      • Comparator: Collator coll = Collator.getInstance(locale);
      • words.sort(coll);

资源包

  • 命名:
    • 国家相关:baseName_language_country
    • 语言相关:basName_language
  • 加载:
    • ResourceBundle resources = ResourceBundle.getBundle(baseName,currentLocale);
  • 属性文件:
    • .porperties : 如ProgramStrings_de_DE.properties
    • 查找字符串: String label = resources.getString("computeButton");
  • 包类:提供字符串以外的资源
    • 命名:ProgramResources_de_DE.java
    • 加载:ResourceBundle bundle = ResourceBundle.getBundle("ProgramResources",locale);
    • 定位:Color backgroundColor = (Color)bundle.getObject("backColor");

脚本/编译/注解

脚本

编译

  • 调用编译器:
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    OutputStream outStream = ...;
    OutputStream errStream = ...;
    int result = compiler.run(null,outStream,errStream,"-sourcepath","src","Test.java");
    
  • 发起编译任务:
    • 捕获诊断消息:
      • DiagnosticCollector<JavaFileObject> collector = new DiagnosticCollector<>();
    • 发起编译:
    JavaCompiler.CompilationTask task = compiler.getTask(
      errorWriter,
      fileManager,
      diagnostics,
      options,
      classes,
      sources);
    Boolean success = task.call();
    

注解

  • 概念:插入到源代码中使用其它工具可以对其进行处理的标签
  • 注解接口:
    modifiers @interface AnnotationName
    {
      elementDeclaration1
      elementDeclaration2
      ......
    }
    //元素声明形式
    type elementName();
    type elementName() default value;
    
  • 注解:
    • @AnnotationName(elementName1=value1,elementName2=value2,......)
    • @BugReport(assignedTo="Harry",severity=10)
  • 注解声明:
    • 类/接口:@Entity public class user {...}
    • 变量:@Param("id") String userID
    • 泛化类/方法中的类型参数:public class Cache<@Immutable V> {......}
  • 注解类型:
    • 非Null检查:@NonNull
    • 类型注解习惯放在其它修饰符后面,而声明注解习惯放到前面

标准注解

  • 编译注解:
    • @Deprecated ---> 注解项为过时的
    • @SuppressWarnings ---> 组织特定类型的警告信息
    • @Override ---> 用在方法上,检查注解的方法是否真正覆盖了超类方法
    • @Generated ---> 代码为工具所自动生成
  • 资源注解:
    • @PostConstruct/@PreDestory ---> 控制对象生命周期,标注方法在对象构建后或移除前,紧接着调用
    • @Resource ---> 资源注入,对象构造时,容器注入该数据源的引用
  • 元注解:
    • @Target ---> 应用于注解,限制该注解应用于哪些项
    • @Retention ---> 注解应该保留多长时间
    • @Document ---> 指定该注解应该包含在注解项文档(javadoc)
    • @Inherited ---> 应用于类,它的子类自动继承同样的注解

安全

数字签名

  • 消息摘要:
    • 指纹对象:MessageDigest alg = MessageDigest.getInstance("SHA-1")
    • 传递字节:alg.update(bytes)
    • 消息摘要:byte[] hash = alg.digest();

加密

  • 对称加密:AES
    • 密码对象:Cipher cipher = Cipher.getInstance(algorithName);
    • 密钥初始化:
      • int mode = ...; Key key = ...;
      • cipher.init(mode,key);
      • update()和doFinal()加密数据块
    • 密钥生成:
      • KeyGenerator keygen = KeyGenerator.getInstance("AES");
      • SecureRandom random = new SecureRandom();
      • keygen.init(random);
      • Key key = keygen.generateKey();
  • 非对称加密:RSA
    • KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
    • SecureRandom random = new SecureRandom();
    • pairgen.intiialize(KEYSIZE,random);
    • KeyPair keypair = pairgen.generateKeyPair();
    • Key publicKey = kepPair.getPublic();
    • Key privateKey = keyPair.getPrivate();
posted on 2020-08-13 09:42  Lith  阅读(320)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3