bingmous

欢迎交流,不吝赐教~

导航

Java高级部分概要笔记

复习

多线程

  1. 程序、进程、线程的概念、区别
  2. 并行、并发
  3. 创建线程的四种方式:继承Thread、实现Runnable接口、实现Callable接口、线程池
  4. 线程的生命周期
  5. 线程的同步方式,三种:同步方法,同步代码块,lock
  6. 线程的通信,notify,notifyAll,wait

常用类

String

  1. 定义的两种方式,内存存放的位置
  2. 常用方法,intern()方法的作用
  3. 与基本数据类型,包装类的转换,与char[]的转换,与byte[]数组的转换,与StringBuilder、StringBuffer()的转换

StringBuffer(),StringBuilder()

  1. 与String的区别,可变,线程安全方面,他们的底层存储都是char型数组
  2. 初始容量:多空出16个,扩容是2倍+2,如果还超过了就是用这个值
  3. 常用方法:增删改差插,翻转可以直接reverse(),也包含String里的一些方法

比较器,Comparable接口,Comparator接口

  1. Comparable接口实现compareTo()方法,一劳永逸,任何地方都可以比较
  2. Comparator接口实现compare()方法,只比较一次

集合

IO流

  1. 节点流:FileInputStream,FileOutputStream,FileReader,FileWriter
  2. 处理流:缓冲流BufferedXxx,转换流InputStreamReader(字节->字符),OutputStreamWriter(字符->字节)

 

 

 


  • 代码:逻辑性代码  vs 功能性代码,逻辑性代码重在逻辑,要知道每一步是干什么的,流程是什么;功能性代码重在功能,是实现的一个功能,不需要完全理解掌握,会用就可以了。

多线程

程序、进程、线程

  • 程序:是为完成特定的任务、用某种语言编写的一组指令的集合。一段静态的代码
  • 进程:是正在一个运行的程序,是操作系统资源分配的基本单位
  • 线程:是程序内部的一条执行流程,一个进程可以执行多个线程,线程是调度和执行的基本单位,每个线程拥有独立的运行栈和程序计数器
  • 一个java应用程序java.exe至少要有三个线程:main()主线程,gc()垃圾回收线程,异常处理线程

并行、并发

  • 多个cpu同时执行多个任务
  • 一个cpu通过时间片轮转的方式同时执行多个任务

使用多线程的优点

  • 提高应用程序的响应,对于图形化界面更有意义,可增强用户体验
  • 提高cpu的利用率
  • 改善程序结构,将复杂的程序分为多个线程,独立运行,利于理解和修改

创建线程的两种方式

  • 继承Thread类,重写run()方法,调用start()方法,共享数据必须是static的,那么后面加锁必须是static的,使用当前类作为锁
  • 实现Runable接口,实现run()方法,创建实现类的对象,将此对象传递给Thread类的构造器,天然支持共享数据
  • 总之:一个线程必须有一个Thead类或子类的对象

Thread类有关的方法

  • 静态方法:
    • Thread.currentThread(),返回当前线程的对象
    • Thread.sleep(long millitime)
  • 一般方法:
    • start(),启动当前线程,调用当前线程的run()方法
    • run(),需要重写Thread类的此方法,将需要执行的操作声明在此方法中
    • join(),线程a调用线程b的join()方法之后,线程a阻塞,直到执行完线程b,线程a才结束阻塞状态
    • yield(),释放当前cpu的执行权
    • getName(),获取线程名字
    • setName(String name)
  • 线程的优先级相关的方法
    • getPriority(), setPriority(int p),1-10,MIN_PRIORITY=1,MAX_PRIORITY=1,NORM_PRIORITY=1

两种创建方式的比较

  • 优先使用实现Runnable接口
    • 没有类的单继承的局限性,
    • 实现的方式更适合处理多个线程共享数据的情况,天然的支持数据共享
  • 联系:Thead类也实现了Runnable接口
  • 相同点:都需要重写run()方法

线程的生命周期

  • Thread类的内部枚举类State中,NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINTED
  • 新建,就绪,运行,阻塞,死亡;
    • 新建-就绪(调用start()方法)
    • 就绪-运行(cpu是否分配时间片,反过来也可以yield(),主动释放执行权)
    • 运行-阻塞(sleep(), b.join(), 同步锁, wait(), suspend()挂起)
      及对应的阻塞-就绪(sleep时间到,join结束,获得同步锁,notify()/notifyAll(),resume())

    • 运行-死亡(正常执行完,调用stop(),错误/异常且 没处理)

线程的同步

  • 多线程同时操作共享数据,出现错误
  • 方式一:同步代码块,synchronized (同步监视器) {},同步监视器也即是锁,可以为任意对象,要求共用一把锁,同步代码块不能多也不能少
    • 实现Runnable接口多线程,可以使用this关键字作为锁
    • 继承Thread类的多线程,可以使用当前类作为锁,ThreadTest.class(类也是对象),这个类对象只会加载一次
  • 方式二:同步方法,方法前声明synchronized,如果操作共享数据的代码都在一个方法里,可以使用同步方法
    • 实现Runnable接口多线程,一个对象创建多个线程,默认锁是this
    • 继承Thread类的多线程,由于要多个类的对象创建多个线程,同步方法必须是static的,此时默认锁是当前类
  • 评价,解决了线程不安全的问题,但是操作同步代码时,只能有一个线程参与,其他线程等待,相当于一个单线程,效率低,可能导致死锁(两个线程,两个锁,这两个锁在两个线程中是相反调用的)
  • 线程安全的单例模式--懒汉式,同步代码块外加if判断实例是否为null,只有在一开始为null时对操作加锁,后面不为null的时候不再需要锁了,提高效率 ----双检锁形式,饿汉式 -- 静态内部类形式
  • 方式三:使用锁lock,JDK5新增,使用lock接口的实现类ReentrantLock,调用lock()和unlock()方法手动的加锁和释放锁

线程的通信

三个方法:

  • wait(), 一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器
  • notify(), 一旦执行此方法,就会唤醒被wait的一个线程,如果有多个线程wait,就唤醒优先级高的
  • notifyAll(), 一旦执行此方法,就会唤醒所有被wait的线程

说明:这三个方法必须使用在同步块或同步方法中,这三个方法的调用者必须是同步代码块或同步方法中的同步监视器,这三个方法是定义在Object类中的。

sleep和wait()方法的异同点:

  • 相同点:一旦执行都可以使得当前线程进入阻塞状态
  • 不同点:
    • 声明位置不同,sleep声明在Thread类中是静态的,wait声明在Object类中
    • 使用要求不同,sleep可以在任何场景下使用,wait只能在同步代码块或同步方法中使用
    • 如果都在同步代码块或同步方法中使用:sleep不释放锁,wait释放锁

JDK5.0新增线程创建方式

  • 方式三:实现Callable接口:可以有返回值、可以抛出异常、支持泛型
    • 1,创建一个实现了Callable接口的类,将此线程需要执行的操作声明在call()中
    • 2,创建Callable接口实现类的一个对象
    • 3,将Callable接口实现类的对象传递给FutureTask构造器中,创建FutureTask的对象
    • 4,将FutureTask的对象传递给Thread类的构造器中,创建Thread类的对象,调用start()方法启动线程
    • 5,使用FutureTask的get()方法获取Callable实现类中call方法的返回值
  • 方式四:使用线程池:思路:提前出创建好多个线程,放入线程池,使用时直接获取,使用完放回池中,避免频繁创建销毁线程,实现重复利用。好处:提高响应速度(减少创建线程的时间),降低资源消耗(重复利用线程池中的线程,不需要每次都创建),便于线程管理
    • 1,提供指定数量的线程池,Exectors.newXxxThreadPool(xxx),返回ExectorService接口的对象service,使用这个对象调用execute(Runnable xxx)(适合实现Runnable接口的)或submit(Callable xxx)(适合实现Callable接口的)
    • 2,执行指定线程的操作,需要提供实现Runnable(execute调用)或Callable(submit调用)接口的类的对象
    • 3,关闭连接池,service.shutdown()

常用类

字符串:String,StringBuffer,StringBuilder

  • String:final类型的类,定义的字符串的两种方式,一种直接赋值,另一种使用new(创建了两个对象,堆中一个,方法区中一个char[]),他们都会存在方法区的常量池中,jdk6在方法区,jdk7/8中静态变量和字符串常量池在堆中,jdk8方法区的实现使用直接内存
    • 字面常量+字面常量:直接返回常量池中的值的地址
    • 变量+字面常量:会在堆中new一个对象,对象中的value指向常量池中的值
    • 字符串的intern()方法:返回值直接返回常量池中的值的地址
  • String常用方法:
    • 查询:length(), charAt(), isEmpty(), endsWith(), startsWith(),contains(), indexOf(), lastIndexOf()
    • 比较:equals(), equalsIgnoreCase(), compareTo(),
    • 变换:toLowerCase(), toUpperCase(), trim(), subString()(左闭右开),
    • 替换: replace()(替换所有), replaceAll()(正则表达式匹配然后替换), replaceFirst()(正则表达式匹配替换第一个),
    • 匹配:match()(正则表达式匹配),
    • 切片:split()(正则表达式切分), 
  • 与基本类型、包装类的转换
    • String -> 基本类型、包装类:调用包装类的parseXxx(str)
    • 基本类型、包装类 -> String:调用String类的String.valueOf(xxx)
  • 与字符数组的转换
    • String -> 字符数组:调用String的toCharArray()
    • 字符数组 -> String:调用String的构造器new String()
  • 与字节数组的转换,编码,解码
    • String -> 字节数组:调用String的getBytes()
    • 字节数组 -> String :调用String的构造器new String()
  • 与StringBuffer,StringBuilder的转换
    • 调用StringBuffer,StringBuilder的构造器new StringBuffer(),new StringBuilder()
    • 调用StringBuffer,StringBuilder的toString()

StringBuffer,StringBuilder:

  • 与String区别:可变,StringBuffer线程安全,StringBuider线程不安全,效率StringBuider > StringBuffer > String
  • 底层都是char[] value 存储,StringBuffer和StringBuilder默认初始容量16(多出16)扩容:原始容量*2+2(不够则是现有大小本身),尽量使用构造器确定容量避免频繁扩容
  • 常用方法:
    • 增:append()
    • 删:delete()
    • 改:setCharAt(), replace(), reverse()
    • 查:charAt()
    • 插:insert()
    • 长度:length()

System中的时间戳,java.util.Date,java.sql.Date

  • System.currentTimeMillis(),距离1970年1月1日的毫秒数,时间戳
  • 两种构造器:无参数构造器、long类型时间戳
  • 两个方法:toString(),getTime()返回date对象当前的时间戳

比较器

  • 实现Comparable接口,自然排序,在任何位置都可以比较,重写compareTo()方法,a.compareTo(b),实现类的所有对象都可以调用
  • 实现Comparator接口,定制排序,只比较一次,重写compare()方法,当元素的类型没有实现Comparable接口,或者排序规则不适用当前操作时,使用Comparator,在别的地方调用实现类的对象,一般只用一次使用匿名内部类

System类,BigInteger类,BigDecimal类

枚举类与注解

枚举类

  • 自定义枚举类
  • 使用enum定义枚举类(本质上是Enum的子类)
  • Enum类中的三个常用方法toString(), values(), valuesOf()
  • 使用enum定义枚举类实现接口

注解

  • JDK内置的三个注解:@Override,@Deprecated,@SuppressWarnings
  • 自定义注解:参考@SuppressWarnings,(使用@interface)
  • JDK四种元注解:@Retention,@Target,@Documented,@Inherited
  • JDK1.8新特性:可重复注解@Repeatable,类型注解(@Target里添加)ElementType.TYPE_PARAMETER,ElementType.TYPE_USE

集合

Collection接口

  • Collection接口的方法:
    • add(), addAll(), size(), isEmpty(), clear(),
    • contains(), containsAll(), remove(), removeAll(), retainAll(), (包含,删除,差集,交集,都会调用equals()方法)
    • equals(), hashCode(),
    • toArray()(与Arrays.asList()相互转换,返回固定大小的原数组),
    • iterator(),返回一个迭代器Iterator,使用hasNext()和next()遍历Collection, 删除remove()(要在next后调只能调一次)

注意:remove只删第一个,removeAll和retainAll分别删除和保留所有调用集合存在于另外一个集合的元素;向Collection接口的实现类的对象中添加元素时,一般元素的所在类要重写equals()方法

说明:向Collection接口中添加元素,要求元素所在类重写equals()方法,不涉及到存储,不用重写hashCode()方法

  • List接口,实现类:ArrayList,LinkedList,Vector
    • ArrayList源码分析:List接口的主要实现类,线程不安全,效率高
      jdk7,初始默认为10,扩容为1.5倍(不够则是现有大小本身);
      jdk8中,初始默认为0,第一次add时为10(不够则是现有大小本身),延迟了数组创建,节省内存,之后扩容为1.5倍
    • LinkedList源码分析:插入、删除效率高,双向链表,first,last分别指向头尾,Node节点为私有内部静态类
    • Vector源码分析:List接口的古老实现类,线程安全,效率低,初始默认为10,扩容为2倍
    • List接口常用方法,除了继承Collection的方法外,List集合里还添加了一些根据索引操作集合元素的方法
      • 重载Collection接口的方法(带索引的):add(), addAll(), remove(), get(), indexOf(), lastIndexOf(), set(), subList()
      • 常用方法:
        • 增:add()
        • 删:remove()
        • 改:set()
        • 查:get()
        • 插:add()
        • 长度:size()
        • 遍历:iterator()
  • Set接口,实现类:HashSet,LinkedHashSet,TreeSet
    • Set接口方法:没有额外定义新的方法,使用的都是Collection中声明过的方法;向Set接口实现类中添加元素,要求元素所在类重写hashCode()和equals()方法(要判断是否重复,hashCode()是为了提高效率设计的)
    • HashSet:线程不安全,底层是数组,jdk7,初始默认16,jdk8,初始为0,第一次添加时为16,底层实现是HashMap,value为PRESENT,一个Object对象(HashMap里会调用value的hashCode()和equals()方法,避免出错),可以存储null
    • LinkedHashSet:HashSet的子类,底层是数组+链表,遍历效率高,增加了一对指针,指向添加的前一个和后一个元素
    • TreeSet:底层是红黑树,不能添加null,只能添加同类的对象,且该类实现了Comparable接口,或使用Comparator定制排序

Map接口

  • 实现类:HashMap,LinkedHashMap,TreeMap,Hashtable,Properties
  • Map接口的方法:
    • put(), putAll(), remove(), clear(), get(), containsKey(), containsValue(), isEmpty(), size(), equals()
    • keySet(), values(), entrySet()(返回Map.Entry类型的entry,Map的内部接口,有getKey(), getValue()方法) 
    • 常用方法:
      • 增:put()
      • 删:remove()
      • 改:put()
      • 查:get()
      • 长度:size()
      • 遍历:keySet(), values(), entrySet()
  • 说明:key所在的类要重写equals()和hashCode()方法(本质上hashCode()是为了存储高效设计的)
  • HashMap:底层jdk7,数组+链表,jdk8,数组+链表+红黑树(链表元素个数大于8,容量大于64转化为红黑树,提高查询效率,新旧元素指向不同),线程不安全,效率高,可以存储null的key和value。
    • 源码分析:jdk7,空参构造器,容量大小16,负载因子0.75(兼顾数组的利用率,链表上的元素数量),临界值=容量*负载因子,大于临界值且当前数组位置元素不为空才会扩容,扩容为原来的两倍,变量名Entry;带容量的构造器,容量大小会初始化为2的整数倍,
    • 源码分析:jdk8:空参构造器,一开始不创建数组,变量名Node,添加第一个元素时,创建数组,容量16,负载因子0.75,元素数量大于临界值不为空才会扩容,某个链表元素数量大于8且容量大于64转化为红黑树,否则扩容为2倍,临界值为2倍,带参数的构造器,返回一个参数2倍2的整数倍的容量
    • 不同:jdk8
  • LinkedHashMap:HashMap的子类,频繁遍历效率高,增加了一对指针before,after,记录添加顺序
  • TreeMap:底层是红黑树,不可存储null的key,插入的key必须是同一个类的对象,能够自然排序或者实现定制排序
  • Hashtable:类似HashMap,线程安全,不能存储null的key和value。
  • Properties:Hashtable的子类,key和value都是String,常用来处理配置文件
    • load(fis) 加载.Properties文件
    • getProperty(), 获取属性
  • CurrentHashMap:实现了分段锁,并发效率更高

Collections工具类,操作Collection和Map等集合的工具类

  • 排序操作:reverse(), shuffle(), sort(), swap()
  • 查找替换:min(), max(), frequency(), copy(), replaceAll(), 【copy()需要dest的size不小于src,可以使用Arrays.asList(new Object[src.size()])创建一个List(这个list是一个Arrays内部类)】
  • synchronizedXxx(), 返回相对应的线程安全的集合,内部对方法加了同步代码快

泛型

参数化类型,泛型保证了程序在编译时没有警告,在运行时也不会有ClassCastException

  • 集合中使用泛型
  • 自定义泛型结构:泛型类、泛型接口;泛型方法(返回值前使用<>指明泛型参数,与泛型类无关)
    • 注意:静态方法中不可以使用泛型类(泛型类是在创建对象时确定泛型类型,静态方法属于类,先于创建对象,无法确定泛型类型);异常类不可以使用泛型,其他:https://www.cnblogs.com/felordcn/p/12874819.html,所有在使用泛型时如果泛型的类型不确定都是不可以的,泛型是一个类型的抽象,不能直接实例化它
  • 泛型的嵌套
  • 泛型的继承:可以继续使用父类的泛型,也可以指明部分泛型类型,也可以新添加
  • 通配符:<?>, <? extends A>, <? super A>(可以写入任何A类或其子类的对象,其他只能写入null)

IO

  • File类的三个构造器:File(String), File(String, String), File(File, String)
  • File类的常用方法:
    • 获取方法:getAbsolutePath(), getPath(), getName(), getParent(), length(), lastModified()
    • 目录的方法:list(), listFiles()
    • File类的重命名:要想为true,file1.renameTo(file2), file1必须存在,file2必须不存在,file1会被移动到file2下
    • File类的判断方法:isDirectory(), isFile(), exists(), canRead(), canWrite(), isHidden()
    • File类的创建:createNewFile(), makdir(), makdirs(), File类的删除:delete()
  • 概念:输入流,输出流,字节流,字符流,节点流,处理流(接在已有流的基础上)
  • 四个抽象基类:InputStream,OutputStream,Read,Writer
  • 节点流(文件流):FileInputStream,FileOutputStream,FileReader,FileWriter,都支持直接String构造器
    • FileRead:read(),read ()返回一个字符,int类型;read(char[]),返回读到的字节数;读到末尾返回-1,(注意将char[] 转换成String时调用String(char[], int, len))
    • FileWriter:write(char[] cbuf),不需要文件存在,默认覆盖,true追加
    • FileInputStream:read(byte[] buffer),返回读取的字节个数,读到末尾返回-1
    • FileOutputStream:write(byte[] buffer),写出
    • 总结:
      • 1,File类实例化,2,流FileReader实例化,3,数据的读入read()写出write(),4,资源的关闭
      • 保证流一定会关闭,使用try-catch-finally处理,注意判断流是否存在,存在时在调用close()
      • 提供具体 的流之前,要判断文件是否存在,读文件要求文件一定存在
  • 缓冲流(处理流的一种,提高读取效率):BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter
    • 方法:read(),write(),readLine(),bw.flush()(将缓冲区的内存刷写到文件)
    • 内部提供一个缓冲区,提高字符流和字节流的读取和写入速度;以节点流为参数;关闭外部流时自动关闭内部流;
    • write.flush()方法,刷新到文件
    • readLine()方法读取一行,没有换行符;newLine(),添加换行符,或者 + "\n"
  • 转换流:是字符流,使用时操作的都是字符,分别继承Reader,Writer
    • InputStreamReader:参数为字节输入流,将字节流转换为字符流读出,显示,默认使用系统编码
    • OutputStreamWriter:参数为字节输出流,将字符流转换为字节流写出,存储,默认使用系统编码
  • 编码:unicode编码只是编码集,为每个字符分配了唯一的字符码,用于存储传输的实现有utf-8,utf-16,utf-32
  • 标准输入输出流:System.in(默认从键盘输入,返回值是InputStream),System.out(默认是PrintStream输出到显示器,可以结合setIn,setOut设置输入输出流)
  • 打印流:PrintStream,PrintWrite,通常配合System.setOut()(设置输出流),System.out改变输出到文件
  • 数据流:DataInputStream,DataOutputStream,读出或写入基本数据类型或字符串,注意写入和读出的顺序必须相同
  • 对象流:ObjectInputStream,ObjectOutputSteam,对象序列化,
    • 注意:
    • 对象所属的类必须是可序列化的(实现Serializable接口)
    • 并且添加一个静态常量static final long serialVersionUID = xxL;同时必须保证类的所有属性必须是序列化的
    • static和transient修饰的变量是不可序列化的,为默认值,不会保存的,可以将不想序列化的属性加transient
    • 实现Externalizable接口的类的序列化可以自定义序列化的属性,包括transient修饰的属性,但static修饰的不可序列化
  • 随机存取文件流:RandomAccessFile,既可以作为输入流,也可以作为输出流
    • 四种模式:r,rw,rwd,rws
    • 不对文件覆盖,对文件内容覆盖,seek()选择覆盖位置,追加使用File类的length方法确定指针位置,getFilePointer()
  • ByteArrayOutputStream
  • BIO/IO,阻塞式IO,基于流的
  • NIO,非阻塞式IO,基于缓冲区的
  • 第三方jar包读写

 

网络编程

  • InetAddress类,代表IP地址

  • * 实例化InetAddress:getByName(String name), getLocalHost()
    *      两个常用方法:getHostName(), getHostAddress()
    * 端口号区分不同进程,IP和端口号组成Socket

TCP编程

  • * 客户端:
    * 1 创建套接字 Socket socket = new Socket()
    * 2 获取套接字的输出流 socket.getOutputStream()
    * 3 往流中写数据 write()
    * 4 关闭资源 close
    
    * 服务器端
    * 1 创建套接字 new ServerSocket()
    * 2 接收套接字** accept()
    * 3 获取套接字的输入流 getInputStream()
    * 4 从流中读数据 read()
    * 5 关闭资源 close()

UDP编程

  • * 客户端
    * 1 创建DatagramSocket
    * 2 创建DatagramPacket,要发送的数据,IP和port
    * 3 使用DatagramSocket发送
    * 4 关闭资源
    * 
    * 服务器端
    * 1 创建DatagramSocket
    * 2 创建DatagramPacket,接收数据,port
    * 3 使用DatagramSocket接收
    * 4 读取接收到的数据
    * 5 关闭资源

URL编程

java.net.URL类, 相关方法:openConnection() * connect() * getInputStream();* 传输协议、主机名、端口、资源地址、参数列表

反射

  • 反射的理解,获取Class实例
    * 通过反射可以在运行时获取任何类的任何信息(创建对象,获取属性、方法,注解等)
    * java.lang.Class:对类的更高层次的抽象, 是对所有类的抽象,所有的类本身都是Class的实例,表示运行时类
    * java.lang.reflection.Xxx:反射中涉及到的类
    *
    * 1, Class的理解
    *      -类的加载,javac.exe进行编译,之后使用java.exe将某个类的字节码文件.class加载到内存.
    *       加载到内存中的类称为运行时类, 此运行时类为Class的一个实例.
    *      -换句话说, Class的实例就是一个运行时类
    *      -类的加载过程:
    *          1,类的加载:将.class文件读入内存,并将这些静态数据转化为方法区的运行时数据结构,
    *          然后创建一个java.lang.Class对象作为类数据的访问入口(引用地址),所有需要访问和使用
    *          类数据只能通过这个类对象,由类的加载器完成
    *          2,链接:将类的二进制代码合并到JVM的运行状态之中的过程,确保类信息符合JVM规范,为类变量分配内存
    *          3,初始化:执行类构造器方法的过程,初始化类变量,父类初始化,正确加锁保证多线程安全
    * 2, 获取Class实例的方式
    *      -Person.class (编译时已经确定了)
    *      -p.getClass() (已经有对象了, 不需要用反射)
    *      -Class.forName(classPath) (最常用, 具有动态性, 运行时才会确定)
    *      -classLoder.loadClass(classPath) (了解)
    * 3, Class实例可以包含java的所有类型, 类、接口、注解、枚举、基本数据类型、void、数组
  • 类加载器
    * 获取加载器:getClass().getClassLoader()
    * 种类:
    *      引导类加载器(负责java平台核心库)、
    *      扩展类加载器(负责lib下的jar)、
    *      系统类加载器(java.class.path下的类)
    *
    * 加载配置文件Properties的两种方式:默认的相对路径不同
    *      1 pros.load() 位置为当前Module
    *      2 classlaod.getResourceAsStream() 使用加载器ClassLoader获取, 位置为src下
  • 创建运行时类对象
    * Class的常用方法:
    *      newInstance(), 一般类要有public的空参构造器,便于反射调用,方便子类默认调用super()
  • 获取运行时类的完整结构
    * 获取当前运行时类的属性结构:返回Field
    *      getFields()(所有的public,包含父类)
    *      getDeclaredFields()(当前类的所有属性)
    *      获取当前属性的权限修饰符、数据类型、变量名:Field类的方法
    *      getModifiers(), getType(), getName(); 权限修饰符类Modifier.toString()方法
    *
    * 获取运行时类的方法结构:返回Method
    *      getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
    *      getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)
    *      获取当前方法的注解 权限修饰符 返回值类型 方法名 参数类型 Exception
    *      @Xxxx
    *      权限修饰符  返回值类型  方法名(参数类型1 形参名1,...) throws XxxException{}
    *      getAnnotations()
    *      getReturnType()
    *      getName()
    *      getParameterTypes()
    *      getExceptionTypes()
    *      
    * 获取构造器结构:返回Constructor
    *      getConstructors():获取当前运行时类中声明为public的构造器(不包含父类的,没有太大意义)
    *      getDeclaredConstructors():获取当前运行时类中声明的所有的构造器
    * 
    * 获取运行时类的父类:返回Class
    *      getSuperclass()
    *      getGenericSuperclass() 获取运行时类的带泛型的父类
    *      获取运行时类的带泛型的父类的泛型:Type类型强转为ParameterizedType类(泛型是参数化类型的类)
    *      getActualTypeArguments()
    *      
    * 获取运行时类实现的接口:返回Type, getInterfaces()
    * 获取运行时类所在的包:返回Package, getPackage()
    * 获取运行时类声明的注解:返回Annotation, getAnnotations()  
  • 调用运行时类的指定结构
    * 调用*运行时类的指定结构(创建对象,调用属性,方法,构造器)
    *      setAccessible(true);保证可调用
    * 
    * 如何操作运行时类中的指定的属性(静态属性?) 
    *      获取属性getDeclaredField(),设置属性set()(null或Xxx.class调用静态属性),获取属性get()
    * 如何操作运行时类中的指定的方法(静态方法?)
    *      获取方法getDeclaredMathod(),调用方法invoke()(null或Xxx.class调用静态方法),返回值是invoke()
    * 如何调用运行时类中的指定的构造器
    *      获取构造器getDeclaredConstructor(),调用newInstance()
  • 反射的应用:AOP与动态代理

Java8新特性

  • 函数式接口、lambda表达式

    • 函数式接口:只有一个抽象方法的接口
    • lambda表达式只能简写函数式接口
  • 方法引用:使用已经实现的方法简写lambda表达式的lambda体
  • 构造器引用
  • 数组引用
  • java.util.Stream API,引入真正的函数式风格,是处理集合的关键抽象概念,可以指定希望对集合进行的操作,可以执行非常复杂的查找、过滤、映射数据等操作,使用Stream API对数据集合进行操作,就类似于使用SQL执行数据库查询。Stream API提供了一种高效且易于处理数据的方式。
  • java8 接口中可以定义静态方法,只能通过接口调用;可以定义默认方法,实现类不必要实现
  • Optional类,解决程序中的空指针问题

Java9新特性

  • 安装包目录变化,没有了jre,大小减少了100多M
  • 模块化系统:可以在源文件目录下创建module-info.java文件
// 导出接口给别的模块使用
module xxx {
    exports com.bingmous.bean; 
}

// 使用别的模块的接口
module xxx {
    requires com.bingmous.bean; 
}
  • REPL工具,像python,scala那样提供交互式编程环境
  • 接口中可以定义私有方法,java8中可以定义默认实现,静态方法(只能接口调用)
  • 钻石操作符语法升级:匿名实现类可以使用钻石操作符,不必再指定泛型类型
  • try结构:java8中可以在try后面的小括号写需要关闭资源的定义,在java9可以在小括号中写关闭资源的变量,此变量为final,在后面的使用中不可改变。
  • String底层存储结构变为byte,原先为char,一个字符为两个字节,其他String相关的也都改了
  • 集合类型创建只读:Collections.unmodifiableList(),及其他List.of(),创建只读对象
  • InputStream新方法TransforTo,直接将一个流的数据读到另一个流
  • Stream新增的api,takeWhile,dropWhile,ofNullable,重载方法iterate
  • Optional新增stream方法,因为Optional也是一个容器

Java10新特性

  • 局部变量类型推断:通过右边推断左边变量类型,var,局部变量和for循环等地方。以下地方不能使用:
    • 不赋值,null
    • lambda表达式左边的函数式接口
    • 方法引用左边的函数式接口
    • 数组的静态初始化
    • 方法的返回类型、参数类型
    • 属性
    • catch块

工作原理:在处理var时,编译器先查看表达式的右边部分,并根据右边变量值的类型进行推断,作为左边变量的类型,然后将该类型写入字节码当中。它不是一个关键字

  • 集合中的copyOf()方法,如果原来的是只读的,就会返回它本身,如果不是只读的,就会新建一个只读的

Java11新特性

  • String新增方法
    • isBlank()
    • strip()去除前后的空白
    • stripTrailing()去除后面的空白
    • stripLeading()去除前面的空白
    • repeat()
    • lines().count(),行数统计
  • Optional新增方法
    • isEmpty()
    • or(),java9新增,返回本身或其他optional,orElse返回本身的内容或其他值
    • orElseThrow(),java10新增,非空返回值,否则抛出异常
  • 可以在var上添加注解
  • 全新的HTTP客户端API,HTTPClient,java9
  • 更简化的编译运行程序
    • 执行第一个类的main方法,不能使用其他文件中的类
  • ZGC(Experimental)

 

 

 

 

 

 

 

 

 

 

 

posted on 2020-05-28 23:34  Bingmous  阅读(42)  评论(0编辑  收藏  举报