Java高级部分概要笔记
复习
多线程
- 程序、进程、线程的概念、区别
- 并行、并发
- 创建线程的四种方式:继承Thread、实现Runnable接口、实现Callable接口、线程池
- 线程的生命周期
- 线程的同步方式,三种:同步方法,同步代码块,lock
- 线程的通信,notify,notifyAll,wait
常用类
String
- 定义的两种方式,内存存放的位置
- 常用方法,intern()方法的作用
- 与基本数据类型,包装类的转换,与char[]的转换,与byte[]数组的转换,与StringBuilder、StringBuffer()的转换
StringBuffer(),StringBuilder()
- 与String的区别,可变,线程安全方面,他们的底层存储都是char型数组
- 初始容量:多空出16个,扩容是2倍+2,如果还超过了就是用这个值
- 常用方法:增删改差插,翻转可以直接reverse(),也包含String里的一些方法
比较器,Comparable接口,Comparator接口
- Comparable接口实现compareTo()方法,一劳永逸,任何地方都可以比较
- Comparator接口实现compare()方法,只比较一次
集合
IO流
- 节点流:FileInputStream,FileOutputStream,FileReader,FileWriter
- 处理流:缓冲流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()
- ArrayList源码分析:List接口的主要实现类,线程不安全,效率高
- 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)
本文来自博客园,作者:Bingmous,转载请注明原文链接:https://www.cnblogs.com/bingmous/p/15643721.html