Java基础知识点总结1:https://developer.aliyun.com/article/1473659
JRE、JDK、JVM区别
- JDK:java 开发工具。是功能⻬全的 Java SDK。它拥有 JRE 所拥有的⼀切,还有编译器(javac)和⼯具(如 javadoc 和 jdb)。它能够创建和编译程序
- JRE: java运行时环境。它是运⾏已编译 Java 程序所需的所有内容的集合,包括 Java 虚拟机(JVM),Java 类库,java 命令和其他的⼀些基础构件
JVM:Java 虚拟机,是运⾏ Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),⽬的是使⽤相同的字节码,它们都会给出相同的结果
简单理解:JDK=JRE(包含JVM+核心类库(JavaAPI))+开发工具
JDK 1.8的新特性
- Lambda表达式
- 简化了匿名委托的使用,让你让代码更加简洁,优雅
语法:() -> {},其中 () 用来描述参数列表,{} 用来描述方法体,-> 为 lambda运算符
新时间日期Api
LocalDate
LocalTime
LocalDateTime
旧的时间日期类缺点
新的在java.time包下
对于日期的计算困难
线程安全问题
接口中的默认方法和静态方法
函数式接口
函数式接口的提出是为了给Lambda表达式的使用提供更好的支持
方法引用和构造器调用
Stream 流
Stream 流
Stream 就好像一个高级的迭代器,但只能遍历一次,在流的过程中,对流中的元素执行一些操作,比如 过滤掉长度大于 10 的字符串、获取每个字符串的首字母 等流的操作可以分为两种类型:
- 中间操作,可以有多个,每次返回一个新的流,可进行链式操作。
- 终端操作,只能有一个,每次执行完,这个流也就用光光了,无法执行下一个操作,因此只能放在最后
什么是函数式接口
有且仅有一个抽象方法的接口,就是函数式接口
提供类型:Supplier<T>接口 特点:只出不进,作为方法/构造参数、方法返回值 消费类型:Consumer<T>接口 特点:只进不出,作为方法/构造参数 断定类型:Predicate<T>接口 特点:boolean类型判断,作为方法/构造参数 转换类型:Function<T>接口 特点:有输入,有输出
JDK1.8之前和JDK1.8之后接口不同
接口指系统对外提供的所有服务(Interface定义的实实在在的接口,即接口类型)【只能有抽象方法】 的入口,是一个抽象类型。一个类通过实现接口的方式,从而继承接口的抽象方法;一个类只能继承一个类,但可以继承多个接口;一个接口不能实现另一个接口,但可以继承多个其他接口
JDK1.8之前:
接口中的变量都是静态变量(public static final),必须显式初始化
接口中所有方法默认都是public abstract
接口没有构造方法,不可以被实例化,但可以被实现(常作为类型使用,也就是父类引用指向子类对象)
实现类必须实现接口的所有的方法
实现类可以实现多个接口(java中的多继承).
JDK1.8之后:
接口里可以有(default关键字修饰的)默认方法(方法体)了
默认方法可以被继承,通过实例调用,可以有多个。如果一个类实现了多个接口,多个接口都定义了多个同样的默认方法时就需要实现类覆盖重写接口中的默认方法,不然会报错,可以使用super来调用指定接口的默认方法。
接口里可以声明(并且可以提供实现)静态方法
接口中的静态方法必须是public的,public修饰符可以省略,static修饰符不能省略,静态方法不能被继承即覆盖,所以只被具体所在的接口调用,接口中静态方法可以有多个。
简单来说:JDK1.8之前接口只能有抽象⽅法,JDK1.8之后接口中可以有不同⽅法,但是⽅法必须⽤static或者default来修饰
接口和抽象类区别
相同点:
- 都代表系统的抽象层;
- 都不能被实例化;
- 都能包含抽象方法(用于描述系统提供的服务,不必提供具体实现)
不同点:
一个类只能继承一个直接父类,但可以实现多个接口;
抽象类有构造器,接口没有构造器;
抽象类中可以有普通⽅法,接口中有没有要区分JDK版本;
抽象类中成员变量⾃⼰定义权限修饰,接口成员变量默认为public static final;
从设计层⾯来说,抽象是对类的抽象,是⼀种模板设计,⽽接⼝是对⾏为的抽象,是⼀种⾏为的规范
多态
接口的多种不同的实现方式即为多态。多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术。
我们在程序中定义的引用变量所指向的具体类型和通过该引用变量的方法调用在编程的时候并不确定,当处于运行期间才确定。就是这个引用变量究竟指向哪一个实例对象,在编译期间是不确定的,只有运行期才能确定,这样不用修改源码就可以把变量绑定到不同的类实例上,让程序拥有了多个运行状态,这就是多态。
Java反射机制
String常用方法
replace() // 字符串的替换 String str1 = "hello word"; String str2 = str1.replace("hello", "hi"); //输出 hi word replaceall() // 字符串全部替换 String str1 = "hello word"; String str2 = str1.replaceAll("o", "1"); //把字符串中的o全部替换为1 输出 hell1 w1rd replaceFirst() // 把字符串中第一个字符替换为X split(String regex) // 字符串拆分 String str1 = "你见过洛杉矶1凌晨四点的1样子吗?"; String[] strs = str1.split("1"); // 通过1进行拆分 for(String s : strs){ System.out.println("s------"+s); } substring(int beginIndex) // 字符串截取 String str1 = "abcdef"; //截取下标为2(含2) String str2 = str1.substring(2); // cdef substring(int beginIndex, int endIndex) // 字符串截取,从下标beginIndex开始截取到endIndex String str1 = "abcdefghi"; // 从下标为2的字符开始截取,截取到下标为4的字符(含2不含4) String str2 = str1.substring(2,4); // cd contains() // 字符串查找 String str = "Hello Word"; boolean result1 = str.contains("l");// 输出 true boolean result2 = str.contains("s");// 输出 false endsWith() // 是否以指定后缀结束 String str = "Hello Word"; boolean result1 = str.endsWith("d");// 输出 true boolean result2 = str.endsWith("s");// 输出 false String.format("%.2f", 0.1356);// 四舍五入(保留两位小数) startsWith(String prefix) // 是否以指定的字符开始 startsWith(String prefix, int offIndex) // 判断指定字符是否在offIndex索引位置上 indexOf(String str) // 返回指定字符在字符串中第一次出现处的索引位置,如果此字符串中没有这个字符,则返回-1 indexOf(String str, int fromIndex) // 返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1 lastindexOf(String str) // 返回指定字符在此字符串中最后一次出现的索引位置,如果此字符串中没有这个字符,则返回 -1 lastindexOf(String str, int fromIndex) // 从fromIndex个字符中找,返回指定字符在此字符串中最后一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1 charAt(int index) // 返回指定索引处的字符。索引范围为从 0 到 length() - 1 int hashCode() // 返回此字符串的哈希码 equals() // 字符串比较 equalsIgnoreCase() // 字符串比较,不区分大小写 getBytes() // 使用平台的默认字符集将字符串编码为 byte 序列,并将结果存储到一个新的 byte 数组中 toCharArray() // 将字符串转换为字符数组 length() // 字符串长度 toLowerCase() // 大写转小写 toUpperCase() // 小写转大写 trim() // 去掉前后空格(中间保留) concat() // 字符串连接(一般用+) intern() // 将内容保存到对象池中 isEmpty() // 判断是否是空字符串
String、String Buffer、Spring Builder区别
- String是不可变字符序列,因为String类是被final修饰的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量的内存空间
String Buffer是可变类,线程安全,多线程操作字符串,效率较低
String Builder也是可变类,非线程安全,单线程操作字符串,效率较快
运行速度:
StringBuilder > StringBuffer > String
适用场景:
String:适用于少量的字符串操作的情况
StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
throw和throws的区别
- throws:跟在方法声明后面,后面跟的是异常类名,可以跟多个异常类名,用逗号隔开,表示抛出异常,由该方法的调用者来处理,throws表示有出现异常的可能性,并不一定出现这些异常
throw:
用在方法体内,后面跟的是异常类对象名,只能抛出一个异常对象名,表示抛出异常,由该方法体内的语句来处理,throw则是抛出了异常,执行throw一定出现了某种异常
final、finally、finalize区别,怎么使用
- final可以修饰类、变量、方法,修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、修饰变量表示该变量是一个常量不能被重新赋值
finally一般作用在try-catch代码块中,在处理异常的时候,通常我们将一定要执行的代码方法写在 finally代码块中,表示不管是否出现异常,该代码块都会执行,一般用来存放一些关闭资源的代码
finalize是一个方法,属于Object类的一个方法,而Object类是所有类的父类,该方法一般由垃圾回收器来调用,当我们调用System.gc() 方法的时候,由垃圾回收器调用finalize(),回收垃圾,对一个对象是否可回收做的最后判断
局部变量和成员变量区别
- 变量:在程序执行的过程中,在某个范围内其值可以发生改变的量。从本质上讲,变量其实是内存中的一小块区域
- 成员变量:方法外部,类内部定义的变量
- 局部变量:类的方法中的变量
作用域
- 成员变量:针对整个类有效
- 局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)
存储位置
- 成员变量:随着对象的创建而存在,随着对象的消失而消失,存储在堆内存中
- 局部变量:在方法被调用,或者语句被执行的时候存在,存储在栈内存中。当方法调用完,或者语句结束后,就自动释放
生命周期
- 成员变量:随着对象的创建而存在,随着对象的消失而消失
- 局部变量:当方法调用完,或者语句结束后,就自动释放
初始值
- 成员变量:有默认初始值
- 局部变量:没有默认初始值,使用前必须赋值
使用原则
在使用变量时需要遵循的原则为:就近原则,首先在局部范围找,有就使用;接着在成员位置找
new出来的对象在JVM中的位置
虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用表的类是否已被加载,解析和初始化过。如果没有,那必须先执行相应的类加载过程。在类加载检查通过后,接下来虚拟机将为新生对象分配内存。
==和equals区别
- ==是比较对象的地址值,即判断是否是同一个对象(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址))
equals重写,这里比较的是内容是否相同
equals在Object中,比较的是是否为同一对象,等价于通过“==”比较这两个对象
==指引用是否相同
equals指值是否相同
String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值。
当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象。
Hashcode和equals的区别
hashCode
hashCode() 的作用是获取哈希码,也称为散列码;
它实际上是返回一个int整数
这个哈希码的作用是确定该对象在哈希表中的索引位置
hashCode() 定义在JDK的Object.java中,这就意味着Java中的任何类都包含有hashCode() 函数
equals
equals它的作用也是判断两个对象是否相等如果对象重写了equals()方法,比较两个对象的内容是否相等;如果没有重写,比较两个对象的地址是否相同,等同“==”。同样的,equals()定义在JDK的Object.java中,这就意味着Java中的任何类都包含有equals()函数。
两者区别
- 若重写了equals(Object obj)方法,则有必要重写hashCode()方法
若两个对象equals(Object obj)返回true,则hashCode()也返回相同的哈希码值
若两个对象equals(Object obj)返回false,则hashCode()不一定返回不同的哈希码值
若两个对象hashCode()返回相同哈希码值,则equals(Object obj)不一定返回true
若两个对象hashCode()返回不同哈希码值,则equals(Object obj)一定返回false
同一对象在执行期间若已经存储在集合中,则不能修改影响hashCode值的相关信息,否则会导致内存泄露问题
break、continue、return的区别及作用
- break:跳出总上一层循环,不再执行循环(结束当前的循环体)
- continue:跳出本次循环,继续执行下次循环(结束正在执行的循环 进入下一个循环条件)
- return:程序返回,不再执行下面的代码(结束当前的方法 直接返回)
重载和重写区别
- 方法的重(Overload):一个类中有多个同名方法,但是参数个数或参数类型不同
方法的重写(Override):在继承关系中,子类对从父类继承过来的方法进行改变,变成自己的方法
构造器不能被继承,因此不能被重写,但可以被重载
方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。
并行和并发有什么区别
两者区别:并发是交替执行,并行是同时执行
- 并发:多个任务在同一个CPU核上,按细分的时间片轮流执行,从逻辑上看任务是同时执行的;
- 并行:多个处理器或多核处理器同时处理多个任务。
线程和进程的区别
- 进程:进程是运行在操作系统上的一个应用程序
- 线程:线程就是进程中的一个任务
例如:
- 打开微信聊天工具就是开启了一个进程
- 在微信中和其中的一个人聊天就会开启一个线程
五个阶段
线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止
关系
关系:线程是进程的基本执行单元,一个进程的所有任务都在线程中执行;进程要想执行任务,必须得有线程。
区别
- 同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间;
- 同一进程内的线程共享本进程的资源,而进程间的资源是独立的。
- 1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位
(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行
(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.
(4)系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。
优缺点
线程执行开销小,但不利于资源的管理和保护;
而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移
浏览器解析并渲染返回的html文件
Java基础知识点总结3:https://developer.aliyun.com/article/1473661