JavaSe基础知识点总结
1、变量
变量是内存中用来存放特定数据类型数据的一块内存空间,它的值是可以改变的。Java中的变量有四个基本属性:变量名,数据类型,存储单元和变量值
变量名:合法的标识符
变量的数据类型:可以是基本类型和引用类型(必须包含类型)
存储单元:存储单元大小是由数据类型决定的,如:int 为4个字节32位
变量值:在存储单元中存放的值
变量的声明格式:
类型 变量名;
2、运算符
运算符种类 符号
赋值运算符 =、 +=、 -=、 *=、 /=、 %=
算术运算符 ++、--、+、-、*、/、%
++自增 --自减 注意前置和后置
关系(比较)运算符 > 、 < 、 >= 、 <=、 ==、 !=
逻辑运算符 &&(且)有短路功能、||(或)有短路功能、!(非)、&(且) 没有短路功能、|(或)
真 && 真 && 假 假
假 && 真 && 真 假
test()& my()
三目运算符 a?b:c
条件判断 ?语句1:语句2
如果条件为真返回1,条件为假返回2
3、数据类型
Java 总共有两种数据类型, 主要有基本类型和引用类型, 基本类型有 8 种, 引用数据类型有3 种
<1> 基本数据类型(系统预先定义好的,拿来就用)
数值类型
整数型(byte,short,int,long)
浮点型(float,double)
字符类型(char)
布尔类型(boolean,只能取值 true 和 false)
<2> 引用数据类型(需要我们自己去定义的)
数组、类、接口
4、java中的方法
语句的集合就是方法
方法定义包括方法头和方法体。
方法头:
修饰符 返回值类型 方法名称(参数)
方法体:{ }之中的内容
5、递归调用
递归就是方法自己调用自己
递归也是一种重复运算
可以递归的问题判断:可以划分为一个或多个子问题,而处理子问题的规则与处理原问题的规则是一样的。
递归需要满足两个条件才会使用
1- 有反复执行的过程(调用自身)
2- 有跳出反复执行的条件(递归出口)
递归算法设计时,需要首先考虑以下两个问题:
1- 确定递归公式。把规模大的、较难解决的问题变成规模较小、易解决的具有重复性同一问题,这是递归问题的难点。
2- 确定边界(终了)条件。在什么情况下需要停止递归?就是问题的边界条件及边界值的确定。
递归的效率要低于普通循环,所以设计程序的时候优先考虑使用循环结构,实在没有更好的办法时再使用递归
6、Scanner类的用法
从键盘输入信息并保存需要如下几步:
第一步: 在程序开头输入
“import java.util.Scanner;”
表示导入键盘输入功能,系统已经写好了,只需要拿到程序中使用就可以了;
第二步: 在程序执行体中输入:
“Scanner input =new Scanner(System.in);”;
第三步:
表示输入功能初始化,
如果要接受一个整型的数据就要定义一个整型的变量来接收,
如:
“int num1=input.nextInt();”,
如果是其他类型的变量, 则“=input.next***();”中的***也要改成相应的类型, 如
7、 import java.util.Scanner;
8、
9、 import javax.print.DocFlavor.INPUT_STREAM;
10、 public class JieChen {
11、 static Scanner input =new Scanner(System.in);
12、 public static void main(String[] args) {
13、 // TODO Auto-generated method stub
14、 int num1=input.nextInt();
15、 System.out.println(num1);
16、 }
17、 public static int jieChen(int x) {
18、 int sum;
19、 if (0==x) {
20、 return 1;
21、 }
22、 sum = x*jieChen(x-1);
23、 return sum;
24、 }
25、 }
7、Java的变量类型(定义变量的位置)
类变量:独立于方法之外的变量,用 static 修饰。作用范围是整个类
实例变量:独立于方法之外的变量,不过没有 static 修饰。作用范围是实例化后的对象
局部变量:类的方法中的变量。使用前必须初始化 作用范围是方法内
8、Java修饰符
1- 访问控制修饰符
public (公有的)对所有的类都可见,使用位置:变量 方法 类 接口
protected(受保护的)对同一包内的类和所有子类可见 使用位置:变量 方法 内部类
default(默认的)在同一包内可见,不用写修饰符,使用位置:变量 方法 类 接口
private(私有的)只在同一类可见,使用位置:变量 方法 内部类
修饰符 |
当前类 |
同包内 |
子孙类 |
其他包 |
public |
是 |
是 |
是 |
是 |
protected |
是 |
是 |
是 |
否 |
default |
是 |
是 |
否 |
否 |
private |
是 |
否 |
否 |
否 |
2- 非访问控制修饰符
static 静态的 使用位置:变量 方法
声明静态变量 静态变量也叫类变量 局部变量不能声明为static变量
类中所有的对象都可以使用,并且只有一份
静态方法 静态方法不能使用非静态变量
final 常态的
final变量 也就是常量 只能初始化一次,之后值不能被改变
final常和static搭配来声明类的常量
final方法 主要目的是防止方法的内容被修改(子类继承)
final类 不能被继承的类
abstract 抽象的
9、基本数据类型间的转换
Boolean型不能和其他的基本类型相互转换
byte char short int long float double
1 2 2 4 8 4 8
10、面向对象三大特性(如果非要说四大特性,就加上抽象)
1- 封装
表现: 函数就是一个最基本的封装体, 类也是一个封装体。
特点: 隐藏属性, 提供对外访问的方法
好处:
1、 提高了代码的复用性;
2、 隐藏了实现细节, 但可以对外提供可访问的方法;
3、 提高了安全性.
2- 继承
定义: 继承表示存在于面向对象程序中的两个类之间的一种关系.当一个类自动拥有另一个类的所有属性( 域和方法) 时, 就称这两个类之间具有继承关系。 被继承的类称为父类( 或超类) , 继承了父类的类被称为子类。
父类与子类之间的关系:
1.共享性 即子类可以共享父类的域和方法。
2.差异性 即子类和父类一定存在某些差异。
3.层次性 即由java规定的单继承性,每个类都处于继承关系中的某一个层面
继承的主要优点:
1.程序结构清晰
2.编程量少
3.易于修改和维护
3- 多态
概念: 对象的多种形态
1.引用多态
父类的引用可以指向本类对象
父类的引用可以指向子类的对象
2.方法多态
创建本类对象时, 调用的方法为本类方法
创建子类对象时, 调用的方法为子类重写或继承的方法
11、类和对象
类是对具有共性事物的抽象描述,是在概念上的一个描述.
对象就是用来描述客观事物的一个实体,有一组属性和方法构成。
Object-orientated
- 1. 对象
客观世界中任何一个具体事物都可以看成一个对象,对象可大可小,可以是一个自然物体,也可以是一种逻辑结构 有针对性
举例:现在讲课的这张桌子,房子、门外停的那辆车、票子
1- 属性:对象的静态特征 成员变量
2- 行为:对象的动态特征 方法
- 2. 封装和信息隐蔽
封装是将有关代码封装在一个对象中,形成一个基本单位,使各个对象之间相对独立,互不干扰
对象中的某些部分对外隐蔽,留下少量接口,与外界联系,这样有利于数据安全
- 3. 抽象
抽象的过程,是将有关事物的共性归纳、集中的过程
抽象的作用就是来表示同一类事物的本质
- 4. 继承与重用
已经建立了一个A类,又想建立一个B类,B类基本上与A相同,只是在A的基础上加了一些属性和行为,我们就没有必要重新建立一个B类,使之继承A类即可
如果B继承于A A叫做B的超类(父类) B叫做A的子类(派生类)
12、class和public class
在一个*.java的文件中,只能有一个public class的声明,但是允许有多个class的声明
被public修饰的类,类名必须和文件名相同
13、package和import
在类中定义包名的语法如下:
package 包名;用来说明当前的文件在哪个包中
import关键字导入包的语法如下:
import com.xxx.*;
在使用import关键字时,可以指定类的完整描述,如果为了使用包中更多的类,可以在使用import关键字指定时在包指定后加上*,这表示可以在程序中使用包中的所有类(不包括子目录中的类)。
14、继承和构造方法
每个类都有构造方法,在没有显示定义构造方法时,java编译器会有一个默认的构造方法,这个构造方法什么也不做
创建对象时,至少会调用一个构造方法
构造方法的名称和类同名,并且没有返回值(这里是真正的没有返回值,并不是void)
一个类可以有多个构造方法,根据使用参数不同,选择性调用
15、方法的重载(overload)
方法有相同的名称,但是参数列表不相同的情形,重载出现在同一个类中
返回值可以不同,但是不能作为重载的判断
我们在使用方法的时候,一定要注意参数的数量及类型顺序
方法重载是让类以统一的方式处理不同类型数据的一种手段。Java构造方法的重载就是在类中可以创建多个构造方法,但具有不同的参数列表(这一点和普通方法的重载是一样的)。调用时通过传递参数的不同来决定具体使用哪个构造方法
16、方法的重写(override)
子类对父类的方法作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。
如果在子类有和父类相同(这里指方法名和参数以及返回值都相同)的方法,子类的这个方法叫方法重写
注意:
1- 如果要构成方法的重写,返回值、方法名、参数列表要相同
2- 修饰符的访问范围不能小于父类
3- 子类的方法不能抛出比父类更多(或更高)的异常
4- 静态的方法不存在重写,但是可以继承。
一、方法重写(0veriding)
在Java程序中,类的继承关系可以产生一个子类,子类继承父类,它具备了父类所有的特征,继承了父类所有的方法和变量。
子类可以定义新的特征,当子类需要修改父类的一些方法进行扩展,增大功能,程序设计者常常把这样的一种操作方法称为重写,也叫称为覆写或覆盖。
重写体现了Java优越性,重写是建立在继承关系上,它使语言结构更加丰富。在Java中的继承中,子类既可以隐藏和访问父类的方法,也可以覆盖继承父类的方法。
在Java中覆盖继承父类的方法就是通过方法的重写来实现的。所谓方法的重写是指子类中的方法与父类中继承的方法有完全相同的返回值类型、方法名、参数个数以及参数类型。
这样,就可以实现对父类方法的覆盖。如果子类将父类中的方法重写了,调用的时候肯定是调用被重写过的方法,那么如果现在一定要调用父类中的方法该怎么办呢?
此时,通过使用super关键就可以实现这个功能,super关键字可以从子类访问父类中的内容,如果要访问被重写过的方法,使用“super.方法名(参数列表)”的形式调用。
如果要使用super关键字不一定非要在方法重写之后使用,也可以明确地表示某个方法是从父类中继承而来的。使用super只是更加明确的说,要从父类中查找,就不在子类查找了。
二、重写规则
在重写方法时,需要遵循以下的规则:
(一) 父类方法的参数列表必须完全与被子类重写的方法的参数列表相同,否则不能称其为重写而是重载。
(二) 父类的返回类型必须与被子类重写的方法返回类型相同,否则不能称其为重写而是重载。..
(三) Java中规定,被子类重写的方法不能拥有比父类方法更加严格的访问权限。编写过Java程序的人就知道,
父类中的方法并不是在任何情况下都可以重写的,当父类中方法的访问权限修饰符为private时,该方法只能被自己的类访问,
不能被外部的类访问,在子类是不能被重写的。如果定义父类的方法为public,在子类定义为private,程序运行时就会报错。
(四) 由于父类的访问权限修饰符的限制一定要大于被子类重写方法的访问权限修饰符,而private权限最小。
所以如果某一个方法在父类中的访问权限是private,那么就不能在子类中对其进行重写。如果重新定义,也只是定义了一个新的方法,不会达到重写的效果。
(五) 在继承过程中如果父类当中的方法抛出异常,那么在子类中重写父类的该方法时,也要抛出异常,
而且抛出的异常不能多于父类中抛出的异常(可以等于父类中抛出的异常)。换句话说,重写方法一定不能抛出新的检查异常,
或者比被重写方法声明更加宽泛的检查型异常。例如,父类的一个方法申明了一个检查异常IOException,在重写这个方法时就不能抛出Exception,
只能抛出IOException的子类异常,可以抛出非检查异常。同样的道理,如果子类中创建了一个成员变量,
而该变量和父类中的一个变量名称相同,称作变量重写或属性覆盖。但是此概念一般很少有人去研究它,因为意义不大。
三、方法重载(Overloading)
方法重载是让类以统一的方式处理不同类型数据的一种手段。调用方法时通过传递给它们的不同个数和类型的参数来决定具体使用哪个方法,这就是多态性。
所谓方法重载是指在一个类中,多个方法的方法名相同,但是参数列表不同。参数列表不同指的是参数个数、参数类型或者参数的顺序不同。
方法的重载在实际应用中也会经常用到。不仅是一般的方法,构造方法也可以重载。
在方法重载时,方法之间需要存在一定的联系,因为这样可以提高程序的可读性,一般只重载功能相似的方法。
重载是指我们可以定义一些名称相同的方法,通过定义不同的参数来区分这些方法,然后再调用时,Java虚拟机就会根据不同的参数列表来选择合适的方法执行
。也就是说,当一个重载方法被调用时,Java用参数的类型或个数来决定实际调用的重载方法。因此,每个重载方法的参数的类型或个数必须是不同。
虽然每个重载方法可以有不同的返回类型,但返回类型并不足以区分所使用的是哪个方法。
当Java调用一个重载方法是,参数与调用参数匹配的方法被执行。在使用重载要注意以下的几点:
1.在使用重载时只能通过不同的参数列表,必须具有不同的参数列表。
2.不能通过访问权限、返回类型、抛出的异常进行重载。
3.方法的异常类型和数目不会对重载造成影响。
4.可以有不同的返回类型,只要参数列表不同就可以了。
5.可以有不同的访问修饰符。
6.可以抛出不同的异常。
四、方法重写与方法重载的区别
17、this关键字
this关键字的使用:this代表当前类的对象。哪个对象调用了this所属的方法,这个this就代表哪个对象。
通过this显式的去使用当前对象的成员(属性、方法)如果需要在一个构造方法中调用另外一个构造方法来初始化信息可以使用this
this平时是隐式调用,也可以显式的调用
this能用在哪些地方?
1-this可以用在成员方法中(访问当前对象的属性, 调用当前对象的方法)
2-this可以用在构造方法中,语法:
this(实参) ;
目的: 代码重用
注意:通过this去调用构造方法时必须是在第一行
构造方法不可以主动调用
18、super关键字
在对象的内部可以代表父类对象
1.可以用super调用父类方法
super.方法名( ) ;
2.可以用super调用父类属性
super.属性;
子类的构造方法中一定会去调用其父类的构造方法
如果未显式调用,则默认调用父类无参构造
如果显式调用,则super()必须位于第一行
如果未显示而父类没有无参构造则程序报错
19、static关键字
概念: static是一个修饰符,用来修饰类的成员(包括了属性、 方法)
static关键字的使用:
特点: 在类加载时就加载(运行、 初始化)静态初始化优于对象的
静态的成员(属性和方法)可以通过 类名.操作符直接访问
注意:
只有在所有对象都是同一个属性值的时候我们才建议到属性上用static修饰
在static的方法或者语句块中不能使用this、 super关键字
在static的方法或者语句块中不能使用非static的成员(属性、 方法)
在非static的方法或者语句块中可以使用static的成员(属性和方法)也可以使用非static的成员
代码块的区别
1- 普通代码块 方法或语句中出现的{ }
2- 构造代码块 类中出现且没有static修饰的{ }
3- 静态代码块 类中出现被static修饰的{ }
静态代码块只执行一次
执行顺序:
静态→main方法→构造代码块→构造方法
20、final关键字
使用final关键字做标识有“最终”的含义
final可以修饰类,方法和变量:
1.final修饰类,则该类不允许被继承
2.final修饰方法,则该方法不允许被重写
3.final修饰变量,则该变量的值只能赋一次,即变为常量
遇到不想被改变的时候就加final
21、Object类,toString,equals方法的重写
Object类的介绍:Object在Java中被定义为一个顶级父类,它是任何类的父类,我们可以显式的继承也可以隐式继承。
Object类常用方法的使用:
1-toString方法:toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明易于读懂的信息表达式。建议所有子类都重写此方法。
2-equals方法: Object类的equals方法默认比较的是对象的引用是否指向同一个内存地址,如果需要判断自定义类型对象内容是否相等,则需要重写equals方法(字符串重写了equals方法)
重写equals方法必须保证如下特性:
- 自反性:如果传入一个非空的引用a a. equals(a)返回true
- 对称性:如果传入两个非空引用a,b a. equals(b)返回true当且仅当b. equals(a)返回true
- 传递性:a. equals(b)返回true,b. equals(c)返回true,那么就有a. equals(c)也返回true
- 一致性:不论调用多少次,结果要保持一致 多次比较中间我们没有修改过两个引用的信息
3-==: 比较的是值是否相同如果相同返回true,否则返回false如果是引用数据类型变量比较的是地址值(地址值相等返回true, 否则返回false)
22、抽象类
在了解抽象类之前,先来了解一下抽象方法。抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法的声明格式为:
abstract void methodName();
抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。不能用抽象类创建对象。原因?:抽象类不象具体类那样描述一类具体事物,它是提取多种具有相似性的具体事物的共同特征而产生的,比如,helicoptor, jet, fighter父类plane,有start(),takeOff(),speedUp(),changeDirection()等方法,这是共性,但现实中有一个具体的plane吗?没有,它是抽象出来的,根本不存在。所以实例化一个plane是没有意义的,因此面向对象程序设计机制禁止对象实例化,抽象类可以声明对象,但是不能使用自身的构造方法创建对象,但是可以使用子类的构造方法进行创建。
public abstract class A{ }
public class B extends A{ }
A a = new B();
定义:包含抽象方法的类称为抽象类。抽象类是专门用来继承的
抽象类和普通类的主要有三点区别:
1) 抽象方法必须为public或者protected( 因为如果为private, 则不能被子类继承, 子类便无法实现该方法),缺省情况下默认为public。
2) 抽象类不能用来创建对象;====》禁止对象实例化
3) 如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为abstract类。
在其他方面,抽象类和普通的类并没有区别
23、接口interface
抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。类继承接口的时候我们叫做实现 一个类实现了某个接口
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
1- 接口与类相似点:
- 一个接口可以有多个方法
- 接口文件也是写在.java文件中,文件名和接口名统一
- 编译后的接口也是.class文件
- 接口的目录结构与类相同
2- 接口与类的区别:
1- 接口不能实例化对象
2- 接口没有构造方法
3- 接口里的方法都是抽象方法
4- 接口不能包含除static和final的成员变量
5- 接口不能被类继承,是被类实现的
6- 类只能单继承,接口支持多继承
3- 接口特性
接口中的方法都会隐式指定为public abstract
接口中的变量都会隐式指定为public static final
接口中的方法不能在接口中实现 就是说不能有定义(方法体)
4- 抽象类和接口的区别
1- 抽象类的方法可以有方法体,但接口不能
2- 抽象类中的成员可以是各种类型的,接口只能是public static final
3- 接口中不能含有静态代码块以及静态方法 抽象类可以有
4- 一个类只能继承一个抽象类,但可以实现多个接口
24、多态
多态存在的必要条件:
1- 继承
2- 重写
3- 父类引用指向子类对象
25、内部类
class 类名{
class 成员内部类名称 {
}
static class 静态内部类名称 {
}
public static void main(String[] args) {
class 局部内部类 {
}
new 类名称() {
匿名内部类 ...
}
}
}
1- 概念
将一个类定义在另一个类里面,对里面那个类就称为内部类(内置类,嵌套类)
访问特点:
内部类可以直接访问外部类中的成员,包括私有成员。
而外部类要访问内部类中的成员必须要建立内部类的对象。
内部类作用:
1) 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类
2) 内部类成员可以直接访问外部类的私有数据,因为内部类被当成其外部类成员,同一个类的成员之间可以互相访问。但外部类不能访问内部类的实现细节。
3) 匿名内部类适用于创建那些仅需要一次使用的类。
4) 内部类比外部类可以多使用三个修饰符:private、protected、static——外部类不可以使用这三个修饰符。
5) 非静态内部类不能拥有静态成员。
2- 成员内部类
位置:成员内部类没有用static修饰且定义在在外部类类体中
1- 成员内部类中的方法可以直接使用外部类的实例变量和实例方法
2- 在成员内部类中可以直接用内部类创建对象
内部类拥有和外部类相同的成员或方法的时候,默认情况下会访问内部类的成员,如果要在内部类中访问外部类的同名成员,需要下面这种形式:
外部类.this.成员变量
外部类.this.成员方法
外部类如果要访问内部类的成员,必须先实例化一个内部类的对象
3- 局部内部类
位置:在方法体或语句块(包括方法、构造方法、局部块或静态初始化块)内部定义的类称为局部内部类。
局部内部类不能加任何访问修饰符,因为它只对局部块有效。
1) 局部内部类只在方法体中有效,就像定义的局部变量一样,在定义的方法体外不能创建局部内部类的对象
2) 在方法内部定义类时,应注意以下问题:
1.方法定义局部内部类同方法定义局部变量一样,不能使用private、protected、public等访问修饰说明符修饰,也不能使用static修饰,但可以使用final和abstract修饰
2.方法中的内部类可以访问外部类成员。对于方法的参数和局部变量,必须有final修饰才可以访问。
3.static方法中定义的内部类可以访问外部类定义的static成员
4- 匿名内部类
内部类的一种简化写法,可以调用其中的方法等等,但是无法有实例化对象。并且匿名内部类必须是继承或者实现一个外部类或者接口。
由于匿名内部类没有名称,所以类体中不能定义构造方法,由于不知道类名也不能使用关键字来创建该类的实例
5- 静态内部类
与类的其他成员相似,可以用static修饰内部类,这样的类称为静态内部类。静态内部类与静态内部方法相似,只能访问外部类的static成员,不能直接访问外部类的实例变量,与实例方法, 只有通过对象引用才能访问。
26、数组
1- 一维数组
声明数组:
数据类型[ ] 数组名;
数据类型 数组名[]; //和上面效果一样,但是不推荐,这是保留C/C++的写法,目的 是为了让C/C++程序员快速理解JAVA语言
2- 二维数组(多维数组)
3- 数组的处理
最常用的处理方式就是利用循环
foreach
数组的使用
1- 数组作为函数的参数 直接传入同类型的数组名
2- 数组作为函数返回值 需要返回的是数组的地址或者引用
4- Arrays类
数组
1- 数组排序
正序和倒序
冒泡排序 选择排序
2- 数组搜索
二分查找(折半查找)
3- Arrays工具类
对数组直接操作
Arrys.相关方法名称(参数);
binarySearch 二分查找
equals 判断值是否相等
fill 范围填充
sort 升序排列
27、常用工具类String
1- String类
2- String类(字符串类)并不是基本数据类型(自定义数据类型)
ps:打上删除线的方法是新版本不推荐的方法
String类的构造方法有11种
StringBuffer和StringBuilder
当对字符串进行修改的时候,需要使用StringBuffer和StringBuilder类。和String类不同的是,StringBuffer和StringBuilder类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder类在Java 5中被提出,它和StringBuffer之间的最大不同在于StringBuilder的方法不是线程安全的(不能同步访问)。
由于StringBuilder相较于StringBuffer有速度优势,所以多数情况下建议使用StringBuilder类。然而在应用程序要求线程安全的情况下,则必须使用StringBuffer类。
StringBuffer的主要方法:
3- 基本类型对应包装类
包装类主要提供了两大类方法:
1. 将本类型和其他基本类型进行转换的方法
2. 将字符串和本类型及包装类互相转换的方法
基本类型转换为字符串有三种方法:
1. 使用包装类的 toString() 方法
2. 使用String类的 valueOf() 方法
3. 用一个空字符串加上基本类型, 得到的就是基本类型数据对应的字符串
4- 日期类
date类
在程序开发中,经常需要处理日期和时间的相关数据,此时我们可以使用java.util包中的Date类。这个类最主要的作用就是获取当前时间,我们来看下Date类的使用:
Calendar类
Calendar类是一个抽象类,在实际使用时实现特定的子类的对象。由于Calendar类是抽象类,且Calendar类的构造方法是protected的,所以无法使用Calendar类的构造方法来创建对象,API中提供了getInstance方法用来创建对象。
a、 创建一个代表系统当前日期的Calendar对象
Calendar c = Calendar.getInstance();//默认是当前日期
b、 创建一个指定日期的Calendar对象
使用Calendar类代表特定的时间,需要首先创建一个Calendar的对象,然后再设定该对象中的年月日参数来完成。
//创建一个代表2013年5月5日的Calendar对象
Calendar c1 = Calendar.getInstance();
c1.set(2013, 5, 5);
simpleDateFormat类
SimpleDateFormat 是一个以与语言环境相关的方式来格式化和分析日期的具体类。 它允许进行格式化(日期->文本)、分析(文本->日期)和规范化。
所以本类可以实现: String 到 Date Date到String的互转
5- Math类
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
Math 的方法都被定义为 static 形式,通过 Math 类可以在主函数中直接调用。
loge
SimpleDateFormat格式字符串规定
28、异常
1- 什么是异常
是程序中的一些错误
异常 错误(error)和异常(exception)两类
按定义分:
系统定义的异常
用户自定义异常
按处理方式划分:
运行时异常
非运行时异常(编译时异常)
2- java中异常的层次结构
3- 异常中使用的关键字
try(检查) catch(捕捉) finally(最终) throw(抛出) throws
异常的语句结构
try{
…………//被检查的代码
}catch(异常类型){
…………//处理异常的代码
}
try{
…………//被检查的代码
}finally{
…………//最终都要执行的部分
}
try{
…………//被检查的代码
}catch(异常类型){
…………//处理异常的代码
}finally{
…………//最终都要执行的部分
}
4- finally关键字
finally需要创建try代码块后面
如果有catch,写在最后一个catch代码块后面
无论是否发生异常,finally块一定会执行
finally用来做清理和善后的工作
权限要高于return
5- throw/throws
throw 是抛出一个异常,无论它是我们自己实例化的还是刚捕获到的
位置是在方法体内
throws 声明当前方法可能发生的异常类型
位置是在方法名后方法体前 )throws 异常类型 {
6- Throwable类的主要方法
getMessage() 获取异常的详细信息
getCause() 返回的对象代表异常原因
toString() 返回一个类的串名称
printStackTrace() 打印tostring()结果和栈信息,也就是定位到代码哪一行报异常
29、枚举enum
enumeration JDK1.5引入的新特性
1- 1.5之前的做法
使用接口定义常量来实现类似枚举的作用
2- 枚举的定义方式
用枚举类型创建的对象(变量),值只能是枚举类型创建时所列举出的,不可以有其他值
3- 枚举的常用操作
遍历 switch
4- enum对象的常用方法
int compareTo(E o) 比较当前的枚举类型和指定对象的顺序
Class
String name() 返回枚举常量的名称
int ordinal() 返回枚举常量的序号
String toString() 返回枚举常量的名称
static
静态的 返回带着指定名称的指定枚举类型的枚举常量 指定枚举类型 指定名称
30、形参和实参
形参,方法头括号里的参数,也就是方法体中使用的部分
实参,给方法传入的参数
传值调用 ,基本数据类型作为参数,会产生值的副本,形参操作不影响实参
传引用调用 ,引用类型作为参数 类类型 接口 数组 传引用类型的地址,形参操作会对实参造成影响
实参给形参传递的都是值 传值的过程都是复制的过程
基本数据类型是将值直接复制 引用类型是将地址进行了赋值
String 和Integer Double等包装类,定义为不可改值的类型immutable,这时会进行特殊处理,要理解为值传递,形参操作不影响实参
原因是以上这些类中,并没有改变对象自身值的操作
String如果要使用引用类型,可以选择使用stringbuffer和stringbuilder
31、Java泛型
1- 概念
泛型的本质是参数化类型
泛型只对编译时有效
2- 为什么要用泛型
相当于类型的通配符(通用匹配),就像是一个虚拟的类型
3- 泛型的使用
1- 泛型类
class FX
2- 泛型方法
public static
3- 集合中的类型(在集合中讲)
4- 泛型的通配符
?为了让父类子类等都通过泛型的使用
5- 泛型的上下边界
上边界
extends Number> 往上只能继承到Number 也就是说只能用Number以及子类作为泛型的具体类型使用
下边界
super Number> 往下只能用到当前类,当前类以及它的父类可以作为泛型的具体类型
6- 泛型使用的好处
1) 类型安全
通过泛型的定义,我们可以界定变量的类型限制,提高Java程序的类型安全
2) 消除类型强制转换
防止类型之间的强制转换,
3) 提高性能
因为消除了强制转换,强制转换的代码不会被编译器插入到字节码中,减少执行部分,从而提高性能
.java → .class
7- 泛型使用的注意事项
1) 泛型的类型参数只能是类类型,不能是基本类型
2) 泛型的类型参数可以有多个
3) 不能对确切泛型类型是instanceof操作
泛型的对象 instanceof FX
4) 不能创建一个确切的泛型类型的数组
32、集合框架(一)(重点)
1- 集合的意义
集合是为了连续的存储数据搭建的框架
数组:可以存储基本数据类型和引用类型,数组的长度是固定的,当元素数量未知的情况下不适合使用
集合:只能存储对象,集合的长度可变,多数情况下使用集合
2- 集合框架的层次结构
collection接口是集合类接口的根接口,这个接口没有实现类,List和Set接口是继承它而来的
Map接口也是集合类接口的一部分,它和collection独立,Map以键值对的形式存储数据
(迭代器)Iterator接口,所有的集合类中,都实现了Iterator接口,用于遍历集合中元素的接口,三个重要的方法:
hasNext() 是否有下一个元素
next() 返回下一个元素
remove() 删除元素
3- List、Set和Map
List(列表):list中的对象是有序的并且元素可以重复的,list是自带索引的,所以查询速度快
Set(集):set里存放的对象是无序的并且不可以重复,set中的对象并不排序,只是简单的加入集合
Map(映射):map中存的是键值对,键不能重复,值可以重复,根据键可以得到值
|
|
是否有序 |
元素是否可以重复 |
collection |
|
|
|
List |
是 |
是 |
|
set |
HashSet |
否 |
否 |
TreeSet |
是(二叉排序树) |
否 |
|
Map |
HashMap |
否 |
key值唯一,value可以重复 |
|
TreeMap |
是(二叉排序树) |
4- List的使用
ArrayList 和 LinkedList这两个类都实现了List接口
这两个在用法上没有区别,LinkedList用在增删操作较多,查询操作较少的情况,ArrayList是在查询多,增删少的操作中。
33、集合框架(二)(重点)
1- Set(集)
Set和List的区别 Set中的元素不重复且无序,List中的元素是可重复且有序
Set有着collection完全一样的接口,所以不像list一样有额外的功能
存入Set中的元素必须都是唯一的
HashSet:为了快速查找设计的Set,以hash算法对元素进行标记
TreeSet:保存次序的Set,基本结构是树结构,提供有序的序列
LinkedHashSet:以链表的形式存储的HashSet
2- Map(映射)
Map接口并不继承collection 但它也是集合的一部分
Map使用键值对存储数据 每个值都有一个和他相关联的键,我们通过键就可以访问到对应的值
HashMap:Map基于散列的形式
TreeMap:Map基于红黑树的形式
LinkedHashMap:链表形式的HashMap
WeakHashMap:一种特殊形式,具有弱键的Map,对象允许释放
3- Iterator(迭代器)
集合全都实现了的接口,用途是遍历集合
4- 集合的遍历
list和set遍历的方式通用 for foreach Iterator
map需要转换成set才能进行遍历
集合的嵌套
34、集合框架(三)(重点)
集合之间的嵌套
list和set结构基本相同,不做介绍
1- list中套list
针对将所有数据都显示时方便
2- list中套map
对显示每条规律的数据的其中一条比较方便
3- map中套map
针对数据的查询很方便
4- map中套list
查询表头方便
不管多复杂的程序,永远脱离不了基础语法
35、文件和流(一)(重点)
1- java.io包介绍
i : input o : output
IO表示程序中将数据输出到程序以外或在程序以外将数据输入到程序内。
也就是程序与外界的数据交流。可以输出到控制台,文件,或网络上的其他计算机上
java.io包也是Java内置的包,其中包含一系列对文件和目录的属性进行操作,对文件进行读写操作的类;
程序中如果要使用到该包中的类,对文件或流进行操作,则必须显式地声明如下语句:
import java.io.*;
2- File类
File类的对象不但可以表示文件,还可以表示目录,在程序中一个File类对象可以代表一个文件或目录;
当创建一个文件对象后, 就可以利用它来对文件或目录的属性进行操作, 如: 文件名、 最后修改日期、文件大小等等;
需要注意的是, File对象并不能直接对文件进行读/写操作, 只能查看文件的属性;
File构造方法:
File(String pathname)
指定文件( 或目录) 名和路径创建文件对象
File类中的常用方法
方 法 原 型 说 明
boolean exists() 判断文件是否存在,存在返回true,否则返回false
boolean isFile() 判断是否为文件,是文件返回true,否则返回false
boolean isDirectory() 判断是否为目录,是目录返回true,否则返回false
String getName() 获得文件的名称
String getAbsolutePath() 获得文件的绝对路径
long length() 获得文件的长度(字节数)
boolean createNewFile() throws IOException
创建新文件,创建成功返回true,否则返回false,有可能抛出IOException异常,必须捕捉
boolean delete() 删除文件,删除成功返回true,否则返回false(删除失败:1.文件不存在2.文件被占用3.权限不足)
File[] listFiles() 返回文件夹内的子文件与子文件夹的数组
3- IO继承结构
IO流的两个顶级接口 Closeable Flushable
IO流的四个顶级类 InputStream OutputStream Reader Writer
字节流
字符流
4- 流的分类
按照数据流向分:
- 从程序向外的叫做输出流
- 从外部向程序的叫输入流
按照流的最小传输单位分:
- 字符流 Unicode(万国码) 一个字符(char)=两个字节(2byte)=16位(16bit)
- 字节流 1字节(1byte)=8位(8bit)
字符流只用来读写文本格式 字符需要编解码
字节流可以读写所有格式 字节流不会对文件进行编解码
按照功能分:
- 节点流
- 处理流
5- FileInputStream和FileOutputStream
FileInputStream类称为文件输入流, 继承于InputStream类, 是进行文件读操作的最基本类;
它的作用是将文件中的数据输入到内存(指程序运行的内存部分)中,我们可以利用它来读文件;
由于它属于字节流,因此在读取Unicode字符(如中文)的文件时可能会出现问题。所以字节流尽量不要读取字符类的文本文件,字节流常用来读取图片,音频,视频等多媒体文件
FileOutputStream类称为文件输出流, 继承于OutputStream类,是进行文件写操作的最基本类;
它的作用是将内存中的数据输出到文件中,我们可以利用它来写文件。
6- FileReader、 FileWriter
FileReader类称为文件读取流, 允许以字符流的形式对文件进行读操作。
FileWriter类 称为文件写入流, 以字符流的形式对文件进行写操作与FileReader类相似, FileReader和FileWriter类需要使用缓冲流进行包装,通过包装来提高效率。
7- BufferedReader、 BufferedWriter
BufferedReader类主要为字符流提供缓冲,以提高效率
BufferedReader类的构造方法:
BufferedReader(Reader in)
将字符读取流对象包装成缓冲读取流对象。
BufferedWriter类 可以为FileWriter类提供缓冲
BufferedWriter的构造方法:
BufferedWriter(Writer out)
将字符写入流对象包装成缓冲写入流对象。
8- BufferInputStream、 BufferOutputStream
BufferInputStream:表示带缓冲的字节输入流;
BufferOutStream:表示带缓冲的字节输出流;
9- DataInputStream、 DataOutputStream
DataInputStream类是数据字节流: 将数据类型带着写进去
要使用DataOutputStream读取数据必须提前知道该文件中数据的存储格式和顺序。读取顺序和写入的顺序要相同。
10- ObjectOutputStream、 ObjectInputStream
ObjectOutputStream: 把对象转换为字节序列的过程称为对象的序列化。
ObjectInputStream:把字节序列恢复为对象的过程称为对象的反序列化。
主要有两种用途:
把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
在网络上传送对象的字节序列。
11- InputStreamReader、 OutputStreamWriter
InputStreamReader 是字节流通向字符流的桥梁: 它使用指定的 charset 读取字节并将其解码为字符。
每次调用 InputStreamReader 中的一个 read() 方法都会导致从底层输入流读取一个或多个字节。 要启用从字节到字符的有效转换, 可以提前从底层流读取更多的字节, 使其超过满足当前读取操作所需的字节。 为了达到最高效率, 可要考虑在 BufferedReader 内包装 InputStreamReader;
BufferedReader in= new BufferedReader(new InputStreamReader(System.in));
OutputStreamWriter 是字符流通向字节流的桥梁
每次调用write()方法都会导致在给定字符(或字符集)上调用编码转换器。在写入底层输出流之前,得到的这些字节将在缓冲区中累积。 可以指定此缓冲区的大小, 不过, 默认的缓冲区对多数用途来说已足够大。 注意, 传递给 write() 方法的字符没有缓冲。 为了获得最高效率,可考虑将OutputStreamWriter包装到BufferedWriter中,以避免频繁调用转换器。
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
12- PrintWriter、 PrintStream
PrintStream在OutputStream基础之上提供了增强的功能, 即可以方便地输出各种类型的数据( 而不仅限于byte型)的格式化表示形式。 PrintStream的方法从不抛出IOEceptin
PrintWriter提供了PrintStream的所有打印方法, 其方法也从不抛出IOException。
与PrintStream的区别: 作为处理流使用时, PrintStream只能封装OutputStream类型的字节流, 而PrintWriter既可以封装OutputStream类型的字节流, 还能够封装Writer类型的字符输出流并增强其功能
36、进程与线程
1.进程和线程的区别:
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程至少包含1个线程(1至n个)。进行中的程序
每一个打开的应用程序就是一个进程.
线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。线程必须依附在进程上
线程和进程一样都分为五个阶段:创建、就绪、运行、阻塞、终止。
多进程是指操作系统能同时运行多个任务(程序)。
多线程是指在同一程序中有多个顺序流在执行。
多线程可以达到高效并充分利用cpu的程序
2.线程的使用方法
java中实现多线程有三种方式:
1- 继承Thread类
2- 实现Runable接口
3- 通过实现callable接口和future对象
继承Java.lang.Thread类,并覆盖run()方法
class MyThread extends Thread {
public void run( ) {
/* 覆盖该方法*/
}
}
实现Java.lang.Runnable接口,并实现run()方法
class MyThread implements Runnable{
public void run( ) {
/* 实现该方法*/
}
}
实现callable接口
class MyThread implements callable>{
public > call(){
/*实现方法*/
}
}
总结:
实现Runnable接口和Callable接口比继承Thread类所具有的优势:
1)适合多个相同的程序代码的线程去处理同一个资源
2)可以避免java中的单继承的限制
3)增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
提醒一下大家:main方法其实也是一个线程。在java中所有的线程都是同时启动的,至于什么时候执行,哪个先执行,完全看谁先得到CPU的资源。
在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM就是在操作系统中启动了一个进程。
3.线程的生命周期
1-新建状态:
使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建 状态。它保持这个状态直到程序 start() 这个线程。
2-就绪状态:
当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪 队列中,要等待JVM里线程调度器的调度。
3-运行状态:
如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处 于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
4-阻塞状态:
如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该 线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪 状态。可以分为三种:
等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到 阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处 理完毕,线程重新转入就绪状态。
5-死亡状态:
一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。死亡状态的线程不可以再执行
37、多线程操作
- 线程调度
线程优先级:java中的线程是具有优先级的,优先级高的线程会获得更多的运行机会。
Java中线程的优先级是用整数来表示的,取值范围是1-10
Thread类中有三个静态常量:
static int MAX_PRIORITY
线程可以具有的最高优先级,取值为10。
static int MIN_PRIORITY
线程可以具有的最低优先级,取值为1。
static int NORM_PRIORITY
分配给线程的默认优先级,取值为5。
可以用Thread类的setPriority和getPriority方法分别来设置和获取线程的优先级
但是线程优先级不能保证线程执行的顺序,只能说明优先级高的线程更加重要
- 线程常用方法
sleep(): 强迫一个线程睡眠N毫秒。
join(): 等待线程终止。
currentThread(): 得到当前线程(拿到当前方法所在的线程对象)。
isDaemon(): 一个线程是否为守护线程。
setDaemon(): 设置一个线程为守护线程。(用户线程和守护线程的区 别在于,是否等待主线程依赖于主线程结束而结束)
setName(): 为线程设置一个名称。
wait(): 强迫一个线程等待。
notify(): 通知一个线程继续运行。
setPriority(): 设置一个线程的优先级。
- 多线程使用的时机
多线程的目的是让程序并发执行,改变原有的串行执行方式,来提高效率,当程序中有两个子系统需要并发执行的时候,就需要使用多线程。
多线程是可以编写出高效率的程序,但是一定要注意,太多的线程却会让程序的执行效率实际上降低,因为线程间的切换也是对CPU资源有开销的,过多的线程会使CPU在上下文(线程之间)切换的时间大于程序执行的时间。
- 线程安全
当多个线程访问某个类时,不管运行环境如何调度,这些线程如何交替运行,我们也不需要在主调试代码中加入额外的同步或者协调,这个类都能做出正确的行为,得出正确的结果,我们称这个类是线程安全的。
37、线程间通信(线程同步)
线程之间的通信方式
线程的同步并不是说线程并行执行,而是指协同工作,将好像两个工人加工同一个零件
1- 同步(synchronized/ volatile)
为了保证同一对象的结果一致有效
使用synchronized同步
1) 获得同步锁
2) 清空工作内存
3) 从主内存拷贝对象副本到工作内存
4) 执行代码
5) 刷新主内存
6) 释放同步锁
volatile是使变量对线程有可见性,volatile 不能和final同时修饰一个字段
总结:开始学习时尽量使用synchronized同步线程,当理解深入后自行决定该使用那一种
2- while轮询(循环询问的意思)
非常浪费CPU系统资源的,比方说一部电话没有铃声,没有震动,我们得一直盯着看来没来电话
还存在内存可见性的问题
3- wait/notify机制
避免了像轮询一样过多的CPU资源占用,就是说CPU的利用率提高了
缺点:如果通知提前发送,而等待后执行,那么等待的线程就可能永远不被唤醒,打乱程序的执行逻辑
守护线程和非守护线程
守护线程是一种提供后台通用服务的线程,比如内存回收线程就是守护线程。
守护线程并不是程序不可或缺的一部分。
守护线程和非守护线程没有本质区别,但是当非守护线程全部执行完成时,守护线程也就没有作用了,随之会停止。
将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:
(1) thread.setDaemon(true)必须在thread.start()之前设置,否则会抛出一个IllegalThread StateException异常。不能把正在运行的常规线程设置为守护线程。
(2) 在Daemon线程中产生的新线程也是Daemon的。
(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
38、线程死锁+守护线程
线程死锁
1- 死锁的概念
多个线程同时被阻塞,这些线程中的一个或者全部都在等待某个资源被释放,由于线程无限期的阻塞,程序不可能正常终止的情况
2- 死锁产生的四个必要条件
1) 互斥使用,当一个资源被一个线程占用时,其它线程不能使用
2) 不可抢占,资源不能被资源请求者从资源占有者那里抢夺,只能由占有者主动释放
3) 请求和保持,请求者在请求其他资源的时候还对原有的资源保持占有
4) 循环等待,线程1占有线程2的资源,线程2占有线程3的资源,线程3占有线程1的资源,这样就是一个等待环路。
当以上四个条件都成立的时候,就会形成死锁。如果有一个被打破,死锁就解除了。
死锁是我们不希望出现的情况,我们要想方设法的解决它
3- 生产者消费者问题
生产者和消费者同时使用一个存储空间
守护线程
守护线程和非守护线程(用户线程)
守护线程是一种提供后台通用服务的线程,比如内存回收线程就是守护线程。
守护线程并不是程序不可或缺的一部分。
守护线程和非守护线程没有本质区别,但是当非守护线程全部执行完成时,守护线程也就没有作用了,随之会停止。
将线程转换为守护线程可以通过调用Thread对象的setDaemon(true)方法来实现。在使用守护线程时需要注意一下几点:
(1) thread.setDaemon(true)必须在thread.start()之前设置,否则会抛出一个IllegalThread StateException异常。不能把正在运行的常规线程设置为守护线程。
(2) 在Daemon线程中产生的新线程也是Daemon的。
(3) 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。
39、反射机制
1- 反射的概念
JAVA反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为JAVA语言的反射机制。
2- Class类(区别于class关键字)
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。也就是jvm中有N多的实例每个类都有该Class对象。(包括基本数据类型)
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass 方法自动构造的。也就是这不需要我们自己去处理创建,JVM已经帮我们创建好了。
3- 反射的使用
获取Class对象的三种方式:
- Object ——> getClass();
- 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
- 通过Class类的静态方法:forName(String className)
4- 通过反射获取构造方法
5- 通过反射获取成员变量
6- 通过反射获取成员方法
7- 通过反射获取main方法
8- 可变长参数
- 可变长参数的定义方法
- 可变长参数方法的调用
- 可变长参数的使用规则
1、 在调用方法的时候,如果能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法。
2、 如果要调用的方法可以和两个可变参数匹配,则出现错误
3、 一个方法只能有一个可变长参数,并且这个可变长参数必须是该方法的最后一个参数
- 可变长参数使用注意事项
1、 避免带有可变长参数方法的重载
2、 null值有可能引起变长参数方法的二义性
3、 重写变长参数方法一样要遵守方法重写规则(子类重写父类方法)
40、8.0新特性
1- Base64
Base64是一种加密方式
Java 8 内置了 Base64 编码的编码器和解码器。
Base64工具类提供了一套静态方法获取下面三种BASE64编解码器:
基本:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/。
URL:输出映射到一组字符A-Za-z0-9+_,输出是URL和文件。
MIME:输出隐射到MIME友好格式。输出每行不超过76字符,并且使用'\r'并跟随'\n'作为分割。编码输出最后没有行分割。
2- 新的日期时间API
在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:
非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:
Local(本地) − 简化了日期时间的处理,没有时区的问题。
Zoned(时区) − 通过制定的时区处理日期时间。
新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。
软通动力
3- Nashorn JavaScript引擎
Nashorn取代Rhino(JDK 1.6, JDK1.7)成为Java的嵌入式JavaScript引擎。Nashorn完全支持ECMAScript 5.1规范以及一些扩展。它使用基于JSR 292的新语言特性,其中包含在JDK 7中引入的 invokedynamic,将JavaScript编译成Java字节码。
与先前的Rhino实现相比,这带来了2到10倍的性能提升。
4- Optional 类
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
5- Stream
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
stream是将数据,像输入输出流的形式一样来处理
6- 默认方法
Java 8 新增了接口的默认方法。
简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
我们只需在方法名前面加个default关键字即可实现默认方法。
为什么要有这个特性?
首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本程序,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。
7- 函数式接口
函数式接口(Functional Interface)就是一个只具有一个方法的普通接口。
函数式接口可以被隐式转换为lambda表达式。
函数式接口可以对现有的函数友好地支持 lambda。
JDK 1.8之前已有的函数式接口:
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
JDK 1.8 新增加的函数接口:
java.util.function
8- 方法引用
方法引用通过方法的名字来指向一个方法。
方法引用可以使语言的构造更紧凑简洁,减少冗余代码。
方法引用使用一对冒号 :: 。
9- Lambda 表达式
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。
lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:只有一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体只包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。
lambda表达式形式
(参数列表)-> 返回值或表达式或者方法语句
()-> 返回
41、正则表达式
1、 概念和用途
正则表达式定义了字符串的模式。
正则表达式可以用来搜索、编辑或处理文本。
正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。
2、 Java中的使用类
java.util.regex 包主要包括以下三个类:
1- Pattern 类:
pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
2- Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
3- PatternSyntaxException:
PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
^ 输入法为半角并且是英文的状态 shift+6
3、 正则表达式语法
字符 |
说明 |
\ |
将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,"n"匹配字符"n"。"\n"匹配换行符。序列"\\\\"匹配"\\","\\("匹配"("。 |
^ |
匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与"\n"或"\r"之后的位置匹配。 |
$ |
匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与"\n"或"\r"之前的位置匹配。 |
* |
零次或多次匹配前面的字符或子表达式。例如,zo* 匹配"z"和"zoo"。* 等效于 {0,}。 |
+ |
一次或多次匹配前面的字符或子表达式。例如,"zo+"与"zo"和"zoo"匹配,但与"z"不匹配。+ 等效于 {1,}。 |
? |
零次或一次匹配前面的字符或子表达式。例如,"do(es)?"匹配"do"或"does"中的"do"。? 等效于 {0,1}。 |
{n} |
n 是非负整数。正好匹配 n 次。例如,"o{2}"与"Bob"中的"o"不匹配,但与"food"中的两个"o"匹配。 |
{n,} |
n 是非负整数。至少匹配 n 次。例如,"o{2,}"不匹配"Bob"中的"o",而匹配"foooood"中的所有 o。"o{1,}"等效于"o+"。"o{0,}"等效于"o*"。 |
{n,m} |
M 和 n 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,"o{1,3}"匹配"fooooood"中的头三个 o。'o{0,1}' 等效于 'o?'。注意:您不能将空格插入逗号和数字之间。 |
? |
当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是"非贪心的"。"非贪心的"模式匹配搜索到的、尽可能短的字符串,而默认的"贪心的"模式匹配搜索到的、尽可能长的字符串。例如,在字符串"oooo"中,"o+?"只匹配单个"o",而"o+"匹配所有"o"。 |
. |
匹配除"\r\n"之外的任何单个字符。若要匹配包括"\r\n"在内的任意字符,请使用诸如"[\s\S]"之类的模式。 |
(pattern) |
匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果"匹配"集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用"\("或者"\)"。 |
(?:pattern) |
匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用"or"字符 (|) 组合模式部件的情况很有用。例如,'industr(?:y|ies) 是比 'industry|industries' 更经济的表达式。 |
(?=pattern) |
执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?=95|98|NT|2000)' 匹配"Windows 2000"中的"Windows",但不匹配"Windows 3.1"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
(?!pattern) |
执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,'Windows (?!95|98|NT|2000)' 匹配"Windows 3.1"中的 "Windows",但不匹配"Windows 2000"中的"Windows"。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。 |
x|y |
匹配 x 或 y。例如,'z|food' 匹配"z"或"food"。'(z|f)ood' 匹配"zood"或"food"。 |
[xyz] |
字符集。匹配包含的任一字符。例如,"[abc]"匹配"plain"中的"a"。 |
[^xyz] |
反向字符集。匹配未包含的任何字符。例如,"[^abc]"匹配"plain"中"p","l","i","n"。 |
[a-z] |
字符范围。匹配指定范围内的任何字符。例如,"[a-z]"匹配"a"到"z"范围内的任何小写字母。 |
[^a-z] |
反向范围字符。匹配不在指定的范围内的任何字符。例如,"[^a-z]"匹配任何不在"a"到"z"范围内的任何字符。 |
\b |
匹配一个字边界,即字与空格间的位置。例如,"er\b"匹配"never"中的"er",但不匹配"verb"中的"er"。 |
\B |
非字边界匹配。"er\B"匹配"verb"中的"er",但不匹配"never"中的"er"。 |
\cx |
匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是"c"字符本身。 |
\d |
数字字符匹配。等效于 [0-9]。 |
\D |
非数字字符匹配。等效于 [^0-9]。 |
\f |
换页符匹配。等效于 \x0c 和 \cL。 |
\n |
换行符匹配。等效于 \x0a 和 \cJ。 |
\r |
匹配一个回车符。等效于 \x0d 和 \cM。 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。 |
\S |
匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。 |
\t |
制表符匹配。与 \x09 和 \cI 等效。 |
\v |
垂直制表符匹配。与 \x0b 和 \cK 等效。 |
\w |
匹配任何字类字符,包括下划线。与"[A-Za-z0-9_]"等效。 |
\W |
与任何非单词字符匹配。与"[^A-Za-z0-9_]"等效。 |
\xn |
匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,"\x41"匹配"A"。"\x041"与"\x04"&"1"等效。允许在正则表达式中使用 ASCII 代码。 |
\num |
匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,"(.)\1"匹配两个连续的相同字符。 |
\n |
标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。 |
\nm |
标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 n 和 m 是八进制数字 (0-7)。 |
\nml |
当 n 是八进制数 (0-3),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。 |
\un |
匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。 |
42、Java数据结构
1、概念
数据之间存在的联系方式
2、java中的数据结构
1- Bitset(位集合)
char(16bit)
2- Vector(向量)
实现了一个动态的数组,但是不属于集合框架中的
3- Stack(栈)
实现了一个标准的后进先出的栈结构
4- Dictionary(字典)
和map一致实现的是键值对存储,已经完全弃用
5- Hashtable(哈希表)
Java2之后Hashtable被重构,实现了Map接口
6- Properties(属性)
继承了Hashtable,是一个属性集