- 博客(323)
- 收藏
- 关注
原创 Java入门到架构师知识点整理 | IO | 使用Files
从Java 7开始,提供了Files这个工具类,能极大地方便我们读写文件。虽然Files是java.nio包里面的类,但他俩封装了很多读写文件的简单方法,例如,我们要把一个文件的全部内容读取为一个byte[],可以这么写:byte[] data = Files.readAllBytes(Path.of("/path/to/file.txt"));如果是文本文件,可以把一个文件的全部内容读取为String:// 默认使用UTF-8编码读取:String content1 = Files.read
2022-04-29 15:27:08
399
原创 Java入门到架构师知识点整理 | IO | PrintStream和PrintWriter
PrintStream是一种FilterOutputStream,它在OutputStream的接口上,额外提供了一些写入各种数据类型的方法:写入int:print(int)写入boolean:print(boolean)写入String:print(String)写入Object:print(Object),实际上相当于print(object.toString())…以及对应的一组println()方法,它会自动加上换行符。我们经常使用的System.out.println()实际上就
2022-04-29 15:26:36
400
原创 Java入门到架构师知识点整理 | IO | Writer
Reader是带编码转换器的InputStream,它把byte转换为char,而Writer就是带编码转换器的OutputStream,它把char转换为byte并输出。Writer和OutputStream的区别如下:OutputStreamWriter字节流,以byte为单位字符流,以char为单位写入字节(0~255):void write(int b)写入字符(0~65535):void write(int c)写入字节数组:void write(byte[
2022-04-29 15:26:01
368
原创 Java入门到架构师知识点整理 | IO | Reader
Reader是Java的IO库提供的另一个输入流接口。和InputStream的区别是,InputStream是一个字节流,即以byte为单位读取,而Reader是一个字符流,即以char为单位读取:InputStreamReader字节流,以byte为单位字符流,以char为单位读取字节(-1,0~255):int read()读取字符(-1,0~65535):int read()读到字节数组:int read(byte[] b)读到字符数组:int read(ch
2022-04-29 15:25:19
414
原创 Java入门到架构师知识点整理 | IO | 序列化
序列化是指把一个Java对象变成二进制内容,本质上就是一个byte[]数组。为什么要把Java对象序列化呢?因为序列化后可以把byte[]保存到文件中,或者把byte[]通过网络传输到远程,这样,就相当于把Java对象存储到文件或者通过网络传输出去了。有序列化,就有反序列化,即把一个二进制内容(也就是byte[]数组)变回Java对象。有了反序列化,保存到文件中的byte[]数组又可以“变回”Java对象,或者从网络上读取byte[]并把它“变回”Java对象。我们来看看如何把一个Java对象序列化。
2022-04-29 15:24:29
158
原创 Java入门到架构师知识点整理 | IO | 读取classpath资源
很多Java程序启动的时候,都需要读取配置文件。例如,从一个.properties文件中读取配置:String conf = "C:\\conf\\default.properties";try (InputStream input = new FileInputStream(conf)) { // TODO:}这段代码要正常执行,必须在C盘创建conf目录,然后在目录里创建default.properties文件。但是,在Linux系统上,路径和Windows的又不一样。因此,从磁盘
2022-04-29 15:23:53
220
原创 Java入门到架构师知识点整理 | IO | 操作Zip
ZipInputStream是一种FilterInputStream,它可以直接读取zip包的内容:┌───────────────────┐│ InputStream │└───────────────────┘ ▲ │┌───────────────────┐│ FilterInputStream │└───────────────────┘ ▲ │┌───────────────────┐│In
2022-04-29 15:23:03
280
原创 Java入门到架构师知识点整理 | IO | Filter模式
Java的IO标准库提供的InputStream根据来源可以包括:FileInputStream:从文件读取数据,是最终数据源;ServletInputStream:从HTTP请求读取数据,是最终数据源;Socket.getInputStream():从TCP连接读取数据,是最终数据源;…如果我们要给FileInputStream添加缓冲功能,则可以从FileInputStream派生一个类:BufferedFileInputStream extends FileInputStream
2022-04-29 15:20:30
220
原创 Java入门到架构师知识点整理 | IO | OutputStream
和InputStream相反,OutputStream是Java标准库提供的最基本的输出流。和InputStream类似,OutputStream也是抽象类,它是所有输出流的超类。这个抽象类定义的一个最重要的方法就是void write(int b),签名如下:public abstract void write(int b) throws IOException;这个方法会写入一个字节到输出流。要注意的是,虽然传入的是int参数,但只会写入一个字节,即只写入int最低8位表示字节的部分(相当于b
2022-04-29 15:19:38
352
1
原创 Java入门到架构师知识点整理 | IO | InputStream
InputStream就是Java标准库提供的最基本的输入流。它位于java.io这个包里。java.io包提供了所有同步IO的功能。要特别注意的一点是,InputStream并不是一个接口,而是一个抽象类,它是所有输入流的超类。这个抽象类定义的一个最重要的方法就是int read(),签名如下:public abstract int read() throws IOException;这个方法会读取输入流的下一个字节,并返回字节表示的int值(0~255)。如果已读到末尾,返回-1表示不能继续读
2022-04-28 19:11:18
212
原创 Java入门到架构师知识点整理 | IO | IO初认识
IO是指Input/Output,即输入和输出。以内存为中心:Input指从外部读入数据到内存,例如,把文件从磁盘读取到内存,从网络读取数据到内存等等。Output指把数据从内存输出到外部,例如,把数据从内存写入到文件,把数据从内存输出到网络等等。为什么要把数据读到内存才能处理这些数据?因为代码是在内存中运行的,数据也必须读到内存,最终的表示方式无非是byte数组,字符串等,都必须存放在内存里。从Java代码来看,输入实际上就是从外部,例如,硬盘上的某个文件,把内容读到内存,并且以Jav
2022-04-28 18:59:42
163
原创 Java入门到架构师知识点整理 | 集合 | 使用Collections
Collections是JDK提供的工具类,同样位于java.util包中。它提供了一系列静态方法,能更方便地操作各种集合。注意Collections结尾多了一个s,不是Collection!我们一般看方法名和参数就可以确认Collections提供的该方法的功能。例如,对于以下静态方法:public static boolean addAll(Collection<? super T> c, T... elements) { ... }addAll()方法可以给一个Collecti
2022-04-28 18:58:48
306
转载 Java入门到架构师知识点整理 | 集合 | 使用Iterator
Java的集合类都可以使用for each循环,List、Set和Queue会迭代每个元素,Map会迭代每个key。以List为例:List<String> list = List.of("Apple", "Orange", "Pear");for (String s : list) { System.out.println(s);}实际上,Java编译器并不知道如何遍历List。上述代码能够编译通过,只是因为编译器把for each循环通过Iterator改写为了普通的fo
2022-04-28 18:57:04
134
原创 Java入门到架构师知识点整理 | 集合 | 使用Deque
我们知道,Queue是队列,只能一头进,另一头出。如果把条件放松一下,允许两头都进,两头都出,这种队列叫双端队列(Double Ended Queue),学名Deque。Java集合提供了接口Deque来实现一个双端队列,它的功能是:既可以添加到队尾,也可以添加到队首;既可以从队首获取,又可以从队尾获取。我们来比较一下Queue和Deque出队和入队的方法:QueueDeque添加元素到队尾add(E e) / offer(E e)addLast(E e) / of
2022-04-25 16:07:14
357
原创 Java入门到架构师知识点整理 | 集合 | 使用PriorityQueue
我们知道,Queue是一个先进先出(FIFO)的队列。在银行柜台办业务时,我们假设只有一个柜台在办理业务,但是办理业务的人很多,怎么办?可以每个人先取一个号,例如:A1、A2、A3……然后,按照号码顺序依次办理,实际上这就是一个Queue。如果这时来了一个VIP客户,他的号码是V1,虽然当前排队的是A10、A11、A12……但是柜台下一个呼叫的客户号码却是V1。这个时候,我们发现,要实现“VIP插队”的业务,用Queue就不行了,因为Queue会严格按FIFO的原则取出队首元素。我们需要的是优先队列
2022-04-25 16:06:44
139
原创 Java入门到架构师知识点整理 | 集合 | 使用Queue
队列(Queue)是一种经常使用的集合。Queue实际上是实现了一个先进先出(FIFO:First In First Out)的有序表。它和List的区别在于,List可以在任意位置添加和删除元素,而Queue只有两个操作:把元素添加到队列末尾;从队列头部取出元素。超市的收银台就是一个队列:在Java的标准库中,队列接口Queue定义了以下几个方法:int size():获取队列长度;boolean add(E)/boolean offer(E):添加元素到队尾;E remove()/
2022-04-25 16:05:26
159
原创 Java入门到架构师知识点整理 | 集合 | 使用Set
我们知道,Map用于存储key-value的映射,对于充当key的对象,是不能重复的,并且,不但需要正确覆写equals()方法,还要正确覆写hashCode()方法。如果我们只需要存储不重复的key,并不需要存储映射的value,那么就可以使用Set。Set用于存储不重复的元素集合,它主要提供以下几个方法:将元素添加进Set<E>:boolean add(E e)将元素从Set<E>删除:boolean remove(Object e)判断是否包含元素:boolean
2022-04-25 16:04:44
166
原创 Java入门到架构师知识点整理 | 集合 | 使用Properties
在编写应用程序的时候,经常需要读写配置文件。例如,用户的设置:# 上次最后打开的文件:last_open_file=/data/hello.txt# 自动保存文件的时间间隔:auto_save_interval=60配置文件的特点是,它的Key-Value一般都是String-String类型的,因此我们完全可以用Map<String, String>来表示它。因为配置文件非常常用,所以Java集合库提供了一个Properties来表示一组“配置”。由于历史遗留原因,Proper
2022-04-25 16:04:03
155
原创 Java入门到架构师知识点整理 | 集合 | 使用TreeMap
我们已经知道,HashMap是一种以空间换时间的映射表,它的实现原理决定了内部的Key是无序的,即遍历HashMap的Key时,其顺序是不可预测的(但每个Key都会遍历一次且仅遍历一次)。还有一种Map,它在内部会对Key进行排序,这种Map就是SortedMap。注意到SortedMap是接口,它的实现类是TreeMap。 ┌───┐ │Map│ └───┘ ▲ ┌────┴─────┐ │ │┌──────
2022-04-25 15:59:55
142
原创 Java入门到架构师知识点整理 | 集合 | 使用EnumMap
因为HashMap是一种通过对key计算hashCode(),通过空间换时间的方式,直接定位到value所在的内部数组的索引,因此,查找效率非常高。如果作为key的对象是enum类型,那么,还可以使用Java集合库提供的一种EnumMap,它在内部以一个非常紧凑的数组存储value,并且根据enum类型的key直接定位到内部数组的索引,并不需要计算hashCode(),不但效率最高,而且没有额外的空间浪费。我们以DayOfWeek这个枚举类型为例,为它做一个“翻译”功能:import java.tim
2022-04-25 15:59:07
516
原创 Java入门到架构师知识点整理 | 集合 | 编写equals和hashCode
我们知道Map是一种键-值(key-value)映射表,可以通过key快速查找对应的value。以HashMap为例,观察下面的代码:Map<String, Person> map = new HashMap<>();map.put("a", new Person("Xiao Ming"));map.put("b", new Person("Xiao Hong"));map.put("c", new Person("Xiao Jun"));map.get("a"); /
2022-04-25 15:58:21
183
原创 Java入门到架构师知识点整理 | 集合 | 使用Map
我们知道,List是一种顺序列表,如果有一个存储学生Student实例的List,要在List中根据name查找某个指定的Student的分数,应该怎么办?最简单的方法是遍历List并判断name是否相等,然后返回指定元素:List<Student> list = ...Student target = null;for (Student s : list) { if ("Xiao Ming".equals(s.name)) { target = s;
2022-04-25 15:57:35
99
原创 Java入门到架构师知识点整理 | 集合 | 编写equals方法
我们知道List是一种有序链表:List内部按照放入元素的先后顺序存放,并且每个元素都可以通过索引确定自己的位置。List还提供了boolean contains(Object o)方法来判断List是否包含某个指定元素。此外,int indexOf(Object o)方法可以返回某个元素的索引,如果元素不存在,就返回-1。我们来看一个例子:好友添加:huany6880 加入资深Java学习交流圈,并有系统整理了一套java初学/进阶者最佳的学习方法以及路 线图大纲,Java各核心知识点、架构主流技术
2022-04-24 17:31:37
107
原创 Java入门到架构师知识点整理 | 集合 | 使用List
在集合类中,List是最基础的一种集合:它是一种有序列表。List的行为和数组几乎完全相同:List内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,List的索引和数组一样,从0开始。数组和List类似,也是有序结构,如果我们使用数组,在添加和删除元素的时候,会非常不方便。例如,从一个已有的数组{'A', 'B', 'C', 'D', 'E'}中删除索引为2的元素:┌───┬───┬───┬───┬───┬───┐│ A │ B │ C │ D │ E │ │└───┴─
2022-04-24 17:31:01
116
原创 Java入门到架构师知识点整理 | 集合 | 集合简介
什么是集合(Collection)?集合就是“由若干个确定的元素所构成的整体”。例如,5只小兔构成的集合:┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐│ (\_(\ (\_/) (\_/) (\_/) (\(\ │ ( -.-) (•.•) (>.<) (^.^) (='.')│ C(")_(") (")_(") (")_(") (")
2022-04-24 17:30:26
102
原创 Java入门到架构师知识点整理 | 泛型 | 泛型和反射
Java的部分反射API也是泛型。例如:Class<T>就是泛型:// compile warning:Class clazz = String.class;String str = (String) clazz.newInstance();// no warning:Class<String> clazz = String.class;String str = clazz.newInstance();调用Class的getSuperclass()方法返回的Cla
2022-04-24 17:29:53
98
原创 Java入门到架构师知识点整理 | 泛型 | super通配符
我们前面已经讲到了泛型的继承关系:Pair<Integer>不是Pair<Number>的子类。考察下面的set方法:void set(Pair<Integer> p, Integer first, Integer last) { p.setFirst(first); p.setLast(last);}传入Pair<Integer>是允许的,但是传入Pair<Number>是不允许的。和extends通配符相反,这次,
2022-04-24 17:28:44
152
原创 Java入门到架构师知识点整理 | 泛型 | extends通配符
我们前面已经讲到了泛型的继承关系:Pair<Integer>不是Pair<Number>的子类。假设我们定义了Pair<T>:public class Pair<T> { ... }然后,我们又针对Pair<Number>类型写了一个静态方法,它接收的参数类型是Pair<Number>:public class PairHelper { static int add(Pair<Number> p) {
2022-04-22 17:26:39
174
原创 Java入门到架构师知识点整理 | 泛型 | 擦拭法
泛型是一种类似”模板代码“的技术,不同语言的泛型实现方式不一定相同。Java语言的泛型实现方式是擦拭法(Type Erasure)。所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。例如,我们编写了一个泛型类Pair<T>,这是编译器看到的代码:public class Pair<T> { private T first; private T last; public Pair(T first, T last) { t
2022-04-22 17:25:41
94
原创 Java入门到架构师知识点整理 | 泛型 | 编写泛型
编写泛型类比普通类要复杂。通常来说,泛型类一般用在集合类中,例如ArrayList<T>,我们很少需要编写泛型类。如果我们确实需要编写一个泛型类,那么,应该如何编写它?可以按照以下步骤来编写一个泛型类。首先,按照某种类型,例如:String,来编写类:public class Pair { private String first; private String last; public Pair(String first, String last) {
2022-04-22 17:24:37
119
原创 Java入门到架构师知识点整理 | 泛型 | 使用泛型
使用ArrayList时,如果不定义泛型类型时,泛型类型实际上就是Object:// 编译器警告:List list = new ArrayList();list.add("Hello");list.add("World");String first = (String) list.get(0);String second = (String) list.get(1);此时,只能把<T>当作Object使用,没有发挥泛型的优势。当我们定义泛型类型<String>后
2022-04-22 17:23:48
81
原创 Java入门到架构师知识点整理 | 泛型 | 什么是泛型
在讲解什么是泛型之前,我们先观察Java标准库提供的ArrayList,它可以看作“可变长度”的数组,因为用起来比数组更方便。实际上ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当“可变数组”:public class ArrayList { private Object[] array; private int size; public void add(Object e) {...} public void remove(in
2022-04-22 17:22:59
84
原创 Java入门到架构师知识点整理 | 注解 | 处理注解
Java的注解本身对代码逻辑没有任何影响。根据@Retention的配置:SOURCE类型的注解在编译期就被丢掉了;CLASS类型的注解仅保存在class文件中,它们不会被加载进JVM;RUNTIME类型的注解会被加载进JVM,并且在运行期可以被程序读取。如何使用注解完全由工具决定。SOURCE类型的注解主要由编译器使用,因此我们一般只使用,不编写。CLASS类型的注解主要由底层工具库使用,涉及到class的加载,一般我们很少用到。只有RUNTIME类型的注解不但要使用,还经常需要编写。因此,
2022-04-22 17:10:39
109
原创 Java入门到架构师知识点整理 | 注解 | 定义注解
Java语言使用@interface语法来定义注解(Annotation),它的格式如下:public @interface Report { int type() default 0; String level() default "info"; String value() default "";}注解的参数类似无参数方法,可以用default设定一个默认值(强烈推荐)。最常用的参数应当命名为value。元注解有一些注解可以修饰其他注解,这些注解就称为元注解(met
2022-04-22 17:10:00
150
原创 Java入门到架构师知识点整理 | 注解 | 使用注解
什么是注解(Annotation)?注解是放在Java源码的类、方法、字段、参数前的一种特殊“注释”:// this is a component:@Resource("hello")public class Hello { @Inject int n; @PostConstruct public void hello(@Param String name) { System.out.println(name); } @Overrid
2022-04-22 17:09:05
101
原创 Java入门到架构师知识点整理 | 反射 | 动态代理
我们来比较Java的class和interface的区别:可以实例化class(非abstract);不能实例化interface。所有interface类型的变量总是通过某个实例向上转型并赋值给接口类型变量的:CharSequence cs = new StringBuilder();有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?这是可能的,因为Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interface的实
2022-04-22 17:08:16
172
原创 Java入门到架构师知识点整理 | 反射 | 获取继承关系
当我们获取到某个Class对象时,实际上就获取到了一个类的类型:Class cls = String.class; // 获取到String的Class还可以用实例的getClass()方法获取:String s = "";Class cls = s.getClass(); // s是String,因此获取到String的Class最后一种获取Class的方法是通过Class.forName(""),传入Class的完整类名获取:Class s = Class.forName("java
2022-04-22 17:07:35
127
原创 Java入门到架构师知识点整理 | 反射 | 调用构造方法
我们通常使用new操作符创建新的实例:Person p = new Person();如果通过反射来创建新的实例,可以调用Class提供的newInstance()方法:Person p = Person.class.newInstance();调用Class.newInstance()的局限是,它只能调用该类的public无参数构造方法。如果构造方法带有参数,或者不是public,就无法直接通过Class.newInstance()来调用。为了调用任意的构造方法,Java的反射API提供
2022-04-21 18:07:48
113
原创 Java入门到架构师知识点整理 | 反射 | 调用方法
我们已经能通过Class实例获取所有Field对象,同样的,可以通过Class实例获取所有Method信息。Class类提供了以下几个方法来获取Method:Method getMethod(name, Class...):获取某个public的Method(包括父类)Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)Method[] getMethods():获取所有public的Method(包括父类)Method[]
2022-04-21 17:59:31
83
原创 Java入门到架构师知识点整理 | 反射 | 访问字段
对任意的一个Object实例,只要我们获取了它的Class,就可以获取它的一切信息。我们先看看如何通过Class实例获取字段信息。Class类提供了以下几个方法来获取字段:Field getField(name):根据字段名获取某个public的field(包括父类)Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)Field[] getFields():获取所有public的field(包括父类)Field[] getDeclaredF
2022-04-21 17:57:13
103
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人