-
-
- Math常用方法
- 构造方法:子类对象调用父类构造方法
- 接口
- 抽象类
- 日历对象
- Objects 工具类
- Set和Map
- LinkedList:双向链表
- List去重
- 并发/并行
- sychronized
- 线程池 ThreadPool 的使用步骤 优点:1.效率高 2.复用性高 3.节约资源
- File类常用方法
- FileOutputStream 字节输出流
- FileInputStream 字节输入流 (若文件不存在,则会报错)
- FileReader 字符输入流 (若文件不存在,则会报错)
- FileWriter 字符输出流
- Properties 属性集
- 缓冲流
- 转换流
- 序列化流
- 打印流
- 网络编程Socket
- ServerSocket
- 正则表达式
- Lambda的延迟执行
- Lambda方法引用
- Lambda常用函数式接口
- Stream流
- Junit测试
- 反射
- Class字节码文件对象功能
- JavaDoc注解
- 自定义注解
-
Math常用方法
Math.abs(-2.0); //2.0 —— 绝对值
Math.ceil(3.3); //4.0 向上入——ceil天花板
Math.floor(3.6);//3.0 向下入——floor地板
Math.round(5.5);//6.0 四舍五入
Math.pow(2.0,2.0); // 4.0 第一个参数的第二个参数次幂
构造方法:子类对象调用父类构造方法
构造方法的作用是初始化成员变量的。所以子类的初始化过程中,必须先执行父类的初始化动作。子类的构造方法中默认有一个 super() ,表示调用父类的构造方法,父类成员变量初始化后,才可以给子类使用。
public Fu{System.out.println("Fu");}
public Zi{System.out.prinyln("Zi");}
多态的特点:
编译期检查父类:看父类是否有指定成员,如果没有则编译报错
运行时:
1.非静态的成员方法:如果子类有重写,则运行子类重写后的方法
2.其他(静态方法,静态成员变量,非静态成员变量):都使用父类
多态的缺点:
- 父类对象不能调用子类特有成员,如需调用,需要向下转型
多态的优点:
- 在方法的参数上,如果定义的类型是父类类型,则可以接收任意的子类对象
接口
public interface 接口名称{
// 抽象方法 —— 可以省略abstranct,没有方法体,供子类实现使用(继承必须重写)
// 默认方法 —— 不可省略default,供子类调用或者子类重写(继承后可以不重写)
// 子类可以默认使用接口定义的默认方法,假设有100个类使用了这个接口,如果有一天接口增加了新功能,那么所有的子类都要重写,这个时候,只需要在接口写默认方法,那么所有的子类就可以直接调用了。
// 静态方法 —— 供接口直接调用
// 私有方法 —— 供结构中的默认方法或者静态方法调用
}
public abstract 抽象方法{
// 抽象类中可以有任意的成员,可以没有任意成员
}
若方法名与父类重名,则优先调用父类方法。
抽象类
一个类包含抽象方法,那么这个类就必须是抽象类
子类继承父类,要么它也是抽象类,要么它必须重写父类抽象方法
日历对象
Calendar类的月份表示是0——11月 ,星期表示是1-7天,1表示的是周日
Objects 工具类
Object的equals方法容易抛出空指针异常,所以使用Objects的equals可以避免空指针异常
底层实现是:
return (a == b) || (a != null && a.equals(b));
Set和Map
Set和Map存储数据都是无序的,如果想有序存储数据,则使用他们对应的LinkedHashSet和LinkedHashMap就可以了
- boolean containsKey()
- boolean containsValue()
Map的key和value只能存放引用类型,不能存放基本类型(装箱) –> 集合只能存放引用类型,不能存放基本类型(自动装箱)
LinkedList:双向链表
特有功能:能在链表的两端进行操作(增删查)
* linkedList = [a,b,c,d,e,f,g]
* 获取d元素,list.get(4),7/2=3,d的索引是4,所以从末尾开始获取元素
* 在底层其实本质上链表没有索引,如果想获取链表中某个指定索引位置的元素
* 先判断索引和长度/2的值谁更大,如果索引大,则从链表的末尾开始往前进行获取元素
* 如果长度/2的值比较大,则从链表头开始获取元素
* 尽量不要使用普通for遍历LinkedList,效率差,用增强for
List去重
String[] strs = {"12345","67891","12347809933","98765432102","67891","12347809933"};
//直接调用方法contains
if(!list.contains(str)) list.add(str);
并发/并行
并发
:理论上的同时发生,实际上CPU在多个线程种进行高速的切换,单个时刻其实只有一个线程在执行
并行
:实际上的同时发生,在某个时刻,多个线程同时在执行
进程
:指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,一个应用程序可以运行多个进程
线程
:进程内部的一个独立执行单元,一个进程可以同时并发的运行多个线程`
Runnable比Thread优点在哪:Runnable可以被多个线程共享,并且可以继承有共性的父类
字符串是在常量池中存储的
sychronized
非静态方法的同步锁对象是this
静态方法的同步锁对象是该类的字节码对象,如MyTest.class
(绝对唯一)
线程的6种状态:
- New (新建) — start方法前
- Runnable (可运行)
- Blocked (锁阻塞)
- Wait (无限等待) 该方法会释放锁
- TimeWait (计时等待)
- Terminatesd (被终止)
wait()方法会释放锁,notify()方法不会释放锁
线程池 ThreadPool 的使用步骤 优点:1.效率高 2.复用性高 3.节约资源
//1. 创建线程池对象
ExcutorService service = Excutors.newFixedThreadPool(int count); count:包含几个线程对象
//2. 创建要执行的Runnable对象
MyRunnable runnable = new MyRunnable();
//3. 从线程池中获取线程对象,然后调用Runnable里面的run方法
service.submit(runnalbe);//将runnable塞给线程池运行
//4. 关闭线程池
service.shutdown();
File类常用方法
构造方法:
File(String pathName)
File(File parent,String child)
File(String parent,String child)
File对象在创建的时候,需要在构造方法中声明文件的目录
String getAbsolutePath()
获取绝对路径 getAbsoluteFile()String getPath()
获取构造路径String getName()
获取文件/目录名称 getParent() getParentFilelong length()
获取文件 注意不能直接获取文件夹的大小(只能将该文件夹下的内容大小进行相加)
boolean exists()
此File表示的文件/目录是否实际存在 isHidden() 判断文件的隐藏属性是否为trueboolean isDirectory()
此File表示的是否为目录boolean isFile()
此File表示的是否为我文件
boolean createNewFile()
仅当该文件名称不存在时/父路径存在时,创建【一个】新的文件boolean delete()
删除由此File表示的文件或目录 — 删除目录时,目录里面为空才能被删除boolean mkdir()
创建单级目录boolean mkdirs()
创建多级目录,包括任何必须但不存在的父目录
String[] list()
返回一个String数组,表示该File目录中的所有子文件或目录File[] listFiles()
返回一个File数组, 表示该File目录中的所有子文件或目录
调用listFiles方法的File对象,表示的必须是实际存在的目录,否则返回null,无法进行遍历
boolean accept()
File的过滤器,使用方法:匿名内部类,listFiles((new FileFilter(){ @Override public boolean accept(){ return true; } })); //如果返回false,则被过滤掉,如果返回true,则被留下
FileOutputStream 字节输出流
构造方法:
FileOutputStream(File file)
FileOutputStream (String path)
关联文件过程:
1.创建流对象 2.判断文件是否存在 3. 没有,就创建,有,就清空,并和文件关联 前提条件是,父路径必须存在,否则会抛出异常
FileOutputStream(File file,boolean append)
声明是否继续续写文件 true表示追加数据,false表示清空原有数据
void write(int b)
写出字节,每次只能写出一个字节数据 写的是ASCII码表中的整数void write (byte[] b)
写出字节数组void write(byte[] b,int off,int len)
从off
开始,写入len
个字节
FileInputStream 字节输入流 (若文件不存在,则会报错)
int read()
每次可以读取一个字节数据,提升为int类型,取到末尾返回-1read(byte[] b)
每次读取b个长度的字节到数组中,返回读取的有效字节个数,取到末尾返回-1read(byte[] b,int off,int len)
从off
开始,每次读取len个
有效字节数
FileReader 字符输入流 (若文件不存在,则会报错)
构造方法:
FileReader(File file)
FileReader(String name)
int read()
从输入流读取一个字符int read(char[] ch)
从输入流中读取一些字符,并存储到ch
字符数组中
FileWriter 字符输出流
构造方法:
FileWriter(File file)
FileWriter(String name)
void flush()
刷新此输出流,并强制任何缓冲的输出字符被写出,缓冲区满了会自动刷新void write(int c)
void write(char[] chs)
void write(String str)
FileWriter必须关闭流才会写入文件,否则数据只是保存在缓冲区,并未保存到文件
字符流,只能操作文本文件,不能操作图片,视频等非文本文件
当我们单纯读或者写文本的时候,使用字符流,其他情况使用字节流
Properties 属性集
Object setProperty(String key, String value)
保存一对属性String getProperty(String key)
使用此属性列表中指定的键搜索属性值Set<String> stringPropertyNames()
所有键的名称的集合void load(InputStream inStream)
从字节输入流中读取键值对void store(OutputStream out)
将配置信息写入文件
缓冲流
缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组[8192],通过缓冲区读写,减少系统IO 次数,从而提高读写的效率。(想要读写更快,就使用
byte[]
来接收和传递)
BufferedInputStream 字节缓冲输入流
构造方法:BufferedInputStream(InputStream in)
BufferedOutputStream 字节缓冲输出流
构造方法BufferedOutputStream(OutputStream out)
BufferedReader 字符缓冲输入流
构造方法:
BufferedReader(Reader in)
- 特有方法:
String readLine()
读取一行文字
BufferedWriter 字符缓冲输出流
构造方法:
BufferedWriter(Writer out)
- 特有方法:
void newLine
写一行 行分隔符,由系统属性定义符号,如\r\n
、\r
、\n
转换流
【编码转换流】把字节流转换成字符流
InputStreamReader
构造方法:
InputStreamReader(InputStream in)
InputStreamReader (InputStream in, String charset)
字节数据读取出来,读到程序中,按照你指定的编码格式,进行转换,把固定数量的字节转换成对应的字符
字节数据转换成字符数据的一个桥梁
OutputStreamWriter
构造方法:
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out, String charset)
转出转换流,本身是一个字符流,输出的数据是字符,但是先把字符按照指定的编码,把字符转成对应的字节
字符数据通向字节的桥梁
序列化流
【序列化/反序列化】
Serializable
就是一个标记接口,想要序列化,就必须实现这个接口
【瞬态关键字】【transient】修饰的属性不会被序列化
serialVersionUID 固定序列化ID,可以保证反序列化的成功
ObjectOutputStream
构造方法:
ObjectOutputStream(OutputStream out)
void writeObject(Object obj)
将指定对象写出
ObjectInputStream
构造方法:
ObjectInputStream(InputStream in)
Object readObject()
读取一个对象
打印流
PrintStream
构造方法:
PrintStream(String path)
设置打印流的文件位置
System.setOut(ps)
设置系统打印System.out.println()
的流向,–>流向PrintStream创建的文本位置
网络编程Socket
Tcp特点:三次握手,安全可靠,缺点:三次握手导致的速度慢
UDP特点:不需要握手,传输速度块 缺点:不安全,并且大小有限制,64kb
该类实现【客户端】套接字,套接字指的是两台设备之间通讯的端点构造方法:
Socket(String host, int port)
创建套接字对象并将其连接到指定主机指定端口号上,如果指定地址为null,相当于指定地址为回送地址(127.0.0.1)
InputStream getInputStream()
:【接收】获取服务器返回数据的输入流对象
* 如果此Socket具有相关联的通道,则生成InputStream的所有操作也关联该通道
* 关闭生成的InputStream也将关闭相关的SocketOutputStream getOutputStream()
:【发送】获取输出到服务器的输出流对象
* 同上void close()
:关闭此套接字
* 一旦一个socket被关闭,它不可再使用
* 关闭此socket也将关闭相应的InputStream和OutputStreamvoid shutdownOutput()
: 禁用此套接字的输出流
* 任何先前写出的数据将被发送,随后终止输出流
*【传输数据,客户端必须通过该方法,通知服务端数据传输完毕,否则服务端会陷入无限写入等待】
注意事项:
在服务器回写的时候,客户端要么是关闭了输出流,要么就是调用了shutdownOutput()通知服务器已写完毕,否则服务器会一直等待客户端关闭输出流。案例:
客户端写完之后,等待服务器回写数据,但是服务器读取完数据后,在等待客户端关闭输出流或者调用
shutdownOutput()
方法,此刻,便陷入了无限等待
ServerSocket
这个类实现了【服务器】套接字,该对象等待通过网络的请求。
构造方法:
ServerSocket(int port)
使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号
Socket accept()
:侦听并接收连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接
正则表达式
x 字符 x
[abc] a、b 或 c(简单类)
[^abc] 任何字符,除了 a、b 或 c(否定)
[a-zA-Z] a 到 z 或 A 到 Z,两头的字母包括在内(范围)
. 任何字符
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
boolean matches(String regex) 告知字符串是否满足正则表达式
"12345".matches("[1-9][0-9]{4,10}") --> 第一位不为0,第二位0-9,出现4-10次 (总共5-11个数字)
Lambda的延迟执行
public static void showLog(int level, String message){
if(level == 1){
System.out.println(message);
}
}
public static void main(String[] args){
String msg1 = "Hello";
String msg2 = "World";
String msg3 = "Java";
// 调用showLog方法
showLog(2,msg1+msg2+msg3);
}
Lambda方法引用
1.通过对象名引用成员方法:obj :: printUpperCase
2.通过类名称引用静态方法:Math:: abs
3.通过super引用成员方法:super::sayHello
4.通过this引用成员方法 :this::buyHouse 本类的非静态成员方法
5.类的构造器的引用:Person::new
6.数组的构造器的引用: int[]::new
注意事项:
被传递的方法需要能替换接口中的抽象方法
1.参数 【被传递方法】的参数类型必须是【接口中抽象方法】的类型或者其父类型
2.返回值 【被传递方法】的返回值类型必须是【接口中抽象方法】的类型或者其子类型
Lambda常用函数式接口
Supplier接口(用于获取对象数据) Supplier:供应商
T get()
指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据 如:
private static String getString(Supplier<String> sup)
Consumer接口(用于消费对象数据) Consumer:消费者
void accept(T t)
消费一个指定泛型的数据 —> 如:输出tdefault Consumer<T> andThen(Consumer<? super T> after)
消费一个数据的时候,首先做一个操作,然后再做一个操作,实现组合
若after为null,会提前抛出异常,这样做的好处就是,不需要执行Lambda里面写的代码了,节约了性能
Predicate接口(用于判断/与或非) Predicate:断言,表明
boolean test(T t)
用于条件判断的 场景 —> 如:str.length() > 5
default Predicate<T> and(Pridicate<? super T> other)
条件判断就会存在与或非,and()就是将两个条件语句“并且”在一起,相当于 &&default Predicate<T> or(Pridicate<? super T> other)
条件判断,或 ||default Predicate<T> negate()
条件判断, 非 !
Function接口(用于类型转换)
R apply(T t)
根据类型T的参数获取类型为R的结构—> 如:String转Integer类型default <V> Function<T,V> andThen(Function<? super R,? extends V> after)
将T->R->V,该方法同样用于“先做什么,再做什么”的场景,和 Consumer 中的 andThen 差不多
延迟方法:只是在拼接Lambda函数模型的方法,并不立即执行得到结果。
终结方法:根据拼好的Lambda函数模型,立即执行得到结果值的方法。
通常情况下,这些常用的函数式接口中唯一的抽象方法为终结方法,而默认方法为延迟方法。但这并不是绝对的
Stream流
Stream流是一个来自数据源的元素队列并支持聚合操作
* 元素是特定类型的对象,形成一个队列。
* 数据源流的来源。可以是集合,数组,I/O channel,产生器generator等
* 聚合操作类似SQL语句一样的操作,比如filter,map,reduce,find,match,sorted等。
和以前的Collection操作不同,Stream操作还有两个基础的特征:
* Pipelinging:中间操作都会返回流对象本身。这样多个操作可以串联成一个管道,如同流式风格(fluent style)。这样做可以对操作进行优化,比如延迟执行(laziness)和短路终结(short-circuiting)
* 内部迭代:以前对集合遍历都是通过Iterator或者For-Each的方式,显式的集合外部进行迭代,这叫做外部迭代。Stream提供了内部迭代的方式,通过访问者模式(Visitor)实现。
获取Stream流:
所有的Collection集合都可以通过stream()方法获取流
数组可以用过Stream接口的静态方法,Stream.of(int[] arr)
来获取流对象
Stream的常用功能:
1.过滤:filter
Stream<T> filter(Predicate<? super T> predicate)
可以通过filter方法将一个流转换成另一个子集流
2.统计个数:【终结方法】
long count() 统计流中的元素个数
3.取用前几个
Stream<T> limit(long maxSize)
该方法可以对流进行截取,只取用前几个
4.跳过前几个
Stream<T> skip(long n)
跳过前n个,取后面的元素,若长度大于了总长,则返回长度为0的空流
5.映射(类型转换)
<R> Stream<R> map(Function<? super T,extents R> mapper)
如果需要将流中的元素映射到另一个流中,可以使用map方法
6.组合两个流
static <T> Stream<T> concat(Stream<? extents T> a, Stream<? extents T> b)
如果有两个流,希望合并成为一个流,那么可以使用Stream的静态方法concat
7.遍历【终结方法】
void forEach(Consumer<? super T> action)
逐一处理:和for循环不同,该方法不保证元素的逐一消费动作的流中是有序执行的
8.收集元素到集合中
List collect(static <T> Collector<T, A, List<T>> toList())
将Stream流转换为List集合Set collect(static <T> Collector<T, ?, Set<T>> toSet())
将Stream流转换为Set集合
9.收集元素到数组中
Object[] toArray
将Stream流转换为数组<A> A[] toArray(IntFunction<A[]> generator)
从外面指定泛型参数
10.并发流,多线程操作
Stream parallel()
转换为并发流 –> parallel:平行的,同时发生的
Collection的方法也可以直接得到并发流,parallelStream();
只有在执行终止方法的时候,才会执行之前的过滤、映射、跳过等操作,–>得益于Lambda的延迟执行
每个流对象都只能处理一次,处理完毕之后产生新的流对象
Junit测试
Assert类 —— assert : 断言
Assert.assertEquals(期望的结果,真实的结果)
@Befor
:初始化方法,用于资源申请,所有测试方法在执行之前都会先执行该方法
@After
:释放资源方法,在所有测试方法执行完成后,都会自动执行该方法
反射
Java代码,在计算机中经历的三个阶段
1. Source源代码阶段 ---> 此时类还在电脑的硬盘中 2. Class类对象阶段 ---> 此时类已经被加载到了内存中 3. Runtime运行时阶段 ---> 此时类已经被new出来了 * 框架:半成品软件。可以在框架的基础上进行软件开发,简化编码 * 反射:将类的各个组成部分封装为其他对象,这就是反射机制 * 好处: 1. 可以在程序过程中,操作这些对象。 2. 可以解耦,提高程序的可扩展性。
获取Class字节码文件的三种方式
1. 第一阶段:Class.forName("全类名")
将字节码文件加载进内存,返回Class对象
* 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
2. 第二阶段:类名.class
通过类名的属性class获取
* 多用于参数的传递
3. 第三阶段:对象.getClass()
返回一个Class对象
* 多用于对象的获取字节码的方式
* 结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个
Class字节码文件对象功能
1.获取功能
获取类加载器
ClassLoader getClassLoader
返回加载该字节码文件的类加载器
ClassLoader的方法
URL getResource(String name)
获取指定资源的路径
InputStream getResourceAsStream(String name)
获取指定资源对应的字节流获取成员变量们
Field[] getFields()
:获取所有的public修饰的成员变量
Field getFile(String name)
获取指定名称的public修饰的成员变量
Field[] getDeclaredFields()
获取所有的成员变量,不考虑修饰符
Field getDeclartedField()
获取指定名称的成员变量,不考虑修饰符- 获取构造方法们
Constructor<T>[] getConstructors()
获取所有的public修饰的构造方法
Constructor<T> getConstructor(类<?>...parameterTypes)
如:int.class,String.class
Constructor<T>[] getDeclaredConstructors()
Constructor<T> getDeclaredConstructor()
- 获取成员方法们
Method[] getMethods()
–> 还会获得Object里定义的方法
Method getMethod(String methodName, 类<?>... parameterTypes)
Method[] getDeclaredMethods()
Method getDeclaredMethod(String methodName, 类<?>... parameterTypes)
- 获取类名
String getName()
获取该字节码文件的类名称(非全类名)
2.Field:成员变量
1. 操作成员变量
获取值
get(Object obj)
设置值
set(Object obj, Object value)
忽略访问权限修饰符的安全检查(若操作private数据,会有报错)
setAccessible(true)
暴力反射
3.Constructor:构造方法
创建对象
T newInstance(Object... initargs)
通过构造器新建一个对象,括号内传入构造器的参数
4.Method:成员方法
执行方法 invoke:调用、激活
Object invoke(Object obj, Object... args)
第一个参数:执行对象。 第二个参数:方法参数String getName()
获取方法名(非全名,如public void String get())
类加载器:获取当前类的类加载器,类加载器可以获取src目录下的文件
JavaDoc注解
/**
* @author 作者
* @version 1.0
* @since 1.5
*/
public class JavaDoc{
/**
* 加法运算
* @param a 加数
* @param b 被加数
* @return 返回 a+b 的和
*/
public int add(int a, int b){
return a + b;
}
@Override :检测被该注解标注的方法是否是继承自父类(接口)的
public String toString(){
...
}
@Deprecated : 该注解标注的内容,表示已过时
@SuppressWarnings("all") :压制警告,一般传递参数all
public void show1(){
...
}
}
自定义注解
注解本身就是一个接口,继承Annotation接口,注解中的抽象方法叫做属性
1.格式:
public @interface 注解名称{属性列表} 1. 属性列表:属性返回值有下列取值 * 基本数据类型 * String * 枚举 * 注解 * 以上类型数组 2. 定义了属性,在使用时需要给属性赋值 * 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值 * 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可 * 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略
元注解:用于描述注解的注解
@Target
:描述注解能够作用的位置 Target:目标、靶子
* ElementType取值:
* TYPE:可以作用于类上
* METHOD:可以作用于方法上
* FIELD:可以作用于成员变量上@Retention
:描述注解被保留的阶段 Retention:保留、维持
* RetentionPolicy取值:
* RUNTIME:当前被描述的注解,会保留到class字节码文件中,并被JVM读取到(最常用)
* CLASS:当前被描述的注解,会保留到class字节码文件中,不会被JVM读取
* SOURCE:当前被描述的注解,字节码文件都不会存在该注解@Documented
:描述注解是否被抽取到api文档中@Inherited
:描述注解是否被子类继承 Inherited:继承、遗产 extend:扩展
在程序使用(解析)注解:获取注解中定义的属性值
1. 获取注解定义的位置的对象 (Class对象, Method对象, Field对象)
2. 获取指定的注解
// getAnnotation(Class cls)
//其实就是在内存中生成了一个该注解接口的子类实现对象
public class ProImpl implements Pro{
public String className(){
return "cn.itcast.annotation.Demo1";
}
public String methodName(){
return "show";
}
}
3. 调用注解中的抽象方法获取配置注解的属性值