main()方法是类体中的主方法。该方法从“{”开始,至“}”结束。
public、static和void分别是main()方法的权限修饰符、静态修饰符和返回值修饰符,Java程序中的main()方法必须声明为public static void。String[] args
是一个字符串类型的数组,它是main()
方法的参数,main()方法是程序开始执行的位置。
static修饰符表示该方法是一个静态方法,可以不通过创建类的实例对象来调用。一个类中可以有无数个实例,但只有一个静态域。
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
Java中有8种基本数据类型来存储数值、字符和布尔值
byte、short、int和long
4种类型。数据类型 | 内存空间(8位等于1字节) | 取值范围 |
---|---|---|
byte | 8位 | -128~127 |
short | 16位 | -32768~32767 |
int | 32位 | -2147483648~2147483647 |
long | 64位 | -9223372036854775808~9223372036854775807 |
定义int型变量
int x;
int x,y;
int x = 450,y = -462;
float f1 = 13.23f;
double d1 = 4562.12d;
double d2 = 45678.1564;
public class Gess {
public static void main(String[] args) {
char word = 'd', word2 = '@';
int p = 23045, p2 = 45213;
System.out.println("d在unicode表中的顺序位置是:" + (int) word);
System.out.println("@在unicode表中的顺序位置是:" + (int) word2);
System.out.println("unicode表中的第23045位是:" + (char) p);
System.out.println("unicode表中的第45213位是:" + (char) p2);
}
}
char c1 = '\\';
char char1='\u2605';
System.out.println(c1);
System.out,println(char1);
boolean b;
boolean b1,b2;
boolean b = true;
在程序执行过程中,其值不能被改变的量称为常量,其值能被改变的量称为变量。
字母
、下画线(_)
、美元符号($)
和数字
组成,并且第一个字符不能是数字。标识符不能是Java中的保留关键字。int age;
char char1='r';
+(加)
、-(减)
、*(乘)
、/(除)
、%(求余)
,它们都是二元运算符。“+”和“-”运算符还可以作为数据的正负符号。++a(--a) //表示在使用变量a之前,先将a值加(减)1
a++(a--) //表示在使用变量a之后,再将a值加(减)1
若a++和++a独行来算,都相当于a=a+1
boolean
型。当运算符对应
的关系成立时,运算结果为true,否则为false。
&(&&)
(逻辑与)、
||
(逻辑或)、!
(逻辑非)。逻辑运算符的操作元必须是boolean型数据。
在逻辑运算符中,除了“!”是一元运算符之外,其他都是二元运算符。
111111111 111111111 1111111 11111000
。“&”
,为双目运算符。“按位与”运算的运算法则是:如果两个整型数据a、b对应位都是1,则结果位才是1,否则为0。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同“|”
,为双目运算符。“按位或”运算的运算法则是:如果两个操作数对应位都是0,则结果位才是0,否则为1。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同。
“~”
,为单目运算符。“按位取反”就是将操作数二进制中的1修改为0,0修改为1。“^”
,为双目运算符。“按位异或”运算的运算法则是:当两个操作数的二进制表示相同(同时为0或同时为1)时,结果为0,否则为1。若两个操作数的精度不同,则结果数的精度与精度高的操作数相同
( ? : ) 该运算符有3个操作数,并且需要判断布尔表达式的值。并且决定哪个值应该赋值给变量。
x = (expression) ? value1 if true: value2 if false //expression表达式,value1为若前面成立则赋值给x,否则赋值value2给x。
三元运算符的运算规则为:若条件式的值为true,则整个表达式取值1,否则取值2。
三元运算符等价于if…else语句
。
运算符的优先级决定了表达式中运算执行的先后顺序。通常优先级由高到低的顺序依次是:
增量和减量运算
。
算术运算
。
比较运算
。
逻辑运算
。
赋值运算
。
如果两个运算有相同的优先级,那么左边的表达式要比右边的表达式先被处理。
如果从低精度数据类型向高精度数据类型转换,则永远不会溢出,并且总是成功的;而把高精度数据类型向低精度数据类型转换时,则会有信息丢失,有可能失败。
数据类型转换有两种方式,即隐式转换
与显式转换
。\
低到高
排列的顺序为byte < short < int <
long < float < double。Java语言提供了3种添加注释的方法,分别为单行注释
、多行注释
和文档注释
。
public class Compound {
public static void main(String[] args) {
int x=20;
{
int y=40;
System.out.println(y);
int z=245;
boolean b;
{
b=y>z;
System.out.println(b);
}
}
String word="hello java";
System.out.println(word);
}
}
public class Getif {
public static void main(String[] args) {
int x=40;
int y=20;
boolean b=x>y;
if (b){
System.out.println("x>y");
}
else {
System.out.println("x<y");
}
}
}
public class Getifelse {
public static void main(String[] args) {
int math=100;
int Russian=50;
if (math>60){
System.out.println("数学及格啦");
}
else{
System.out.println("数学寄啦");
}
if (Russian>60){
System.out.println("俄语及格啦");
}
else{
System.out.println("俄语寄啦");
}
}
}
if…else语句可以使用三元运算符进行简化。如下面的代码:
if(a > 0) b = a;
else b = -a;
public class GetTerm {
public static void main(String[] args) {
int x=20;
if (x>30){
System.out.println("a的值大于30");
}
else if (x>10) {
System.out.println("a的值大于10但小于30");
}
else if (x>0){
System.out.println("a的值大于0但小于10");
}
else{
System.out.println("a的值小于0");
}
}
}
public class GetSwitch {
public static void main(String[] args) {
int week=3;
switch (week){
case 1:
System.out.println("Monday");
case 2:
System.out.println("Tuesday");
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
}
}
}
public class GetSum {
public static void main(String[] args) {
int x=1;
int sum=0;
while (x<=10){
sum=sum+x;
++x;
System.out.println("sum="+sum);
}
}
}
public class Cycle {
public static void main(String[] args) {
int a=100;
while (a==60){
System.out.println("ok1");
a--;
}
int b=100;
do {
System.out.println("ok2");
b--;
}while (b==60);
}
}
for(表达式1;表达式2;表达式3){
语句序列
}
其中:表达式1:初始化表达式,负责完成变量的初始化。 表达式2:循环条件表达式,值为boolean型的表达式,指定循环条件。 表达式3:循环后操作表达式,负责修整变量,改变循环条件。
public class Circulate {
public static void main(String[] args) {
int sum=1;
for (int i=1;i<=300;i+=2){
if (i>=100)
sum=sum+i;
}
System.out.println("100到300之间的所有偶数之和为:"+sum);
}
}
public class Repetition {
public static void main(String[] args) {
int d[]={16,14,12,10,8,6,4}; //声明一维数组
System.out.println("从16到4的偶数降序为:"); //输出信息
for (int x:d){ //foreach语句,int x引用的变量,d指定要循环遍历的数组,最后将x输出
System.out.println(x);
}
}
}
break
和continue
两个关键字,这两条跳转语句的跳转效果不同,break是中断循环,continue是执行下一次循环。
public class BreakTast {
public static void main(String[] args) {
for (int i=0;i<=10;i++){
System.out.println(i);
if (i==8){
break;
}
}
System.out.println("end");
}
}
注意:循环嵌套情况下,break语句将只会使程序流程跳出包含它的最内层的循环结构,即只跳出一层循环。
public class BreakInsideNested {
public static void main(String[] args) {
for (int i=0;i<3;i++){ //外部循环
for (int j=0;j<6;j++){ //内部循环
if (j==4){
break;
}
System.out.println("i="+i+"j="+j);
}
}
}
}
外层循环不受任何影响,i最大值达2
public static void main(String[] args) {
Loop:for (int i=0;i<3;i++){
for (int j=0;j<6;j++){
if (j==4){
break Loop;
}
System.out.println("i="+i+"j="+j);
}
}
}
public class ContinueTest {
public static void main(String[] args) {
for (int x=1;x<=20;x++){
if (x%2==0){ //如果x是偶数
continue; //跳到下一循环
}
System.out.println(x); //输出i的值
}
}
}
String
类的实例来处理。数组元素类型 数组名字[];
数组元素类型[] 数组名字;
int arr[];
String str[];
声明数组后,还不能立即访问它的任何元素,因为声明数组只是给出了数组名字和元素的数据类型,要想真正使用数组,还要为它分配内存空间。在为数组分配内存空间时必须指明数组的长度。为数组分配内存空间的语法格式如下:
int x[]=new int[]{1,2,6,74};
int x[]={123,324,435};
new
运算符进行内存分配
声明二维数组的语法如下:for循环
来实现。
遍历一维数组很简单,也很好理解,下面详细介绍遍历二维数组的方法。
遍历二维数组需使用双层for循环,通过数组的length
属性可获得数组的长度。Arrays
类的静态方法fill()
来对数组中的元素进行替换。该方法通过各种重载形式可完成对任意类型的数组元素的替换。Arrays
类的静态sort()
方法可以实现对数组的排序。sort()方法提供了多种重载形式,可对任意类型的数组进行升序排序。Arrays
类的copyOf()
方法与copyOfRange()
方法可以实现对数组的复制。copyOf()
方法是复制数组至指定长度,copyOfRange()
方法则将指定数组的指定长度复制到一个新数组中。
1. copyOf()
方法
该方法提供了多种重载形式,用于满足不同类型数组的复制。copyOfRange()
方法
该方法同样提供了多种重载形式。Arrays
类的binarySearch()
方法,可使用二分搜索法来搜索指定数组,以获得指定对象。该方法返回要搜索元素的索引值。binarySearch()方法提供了多种重载形式,用于满足各种类型数组的查找需要。binarySearch()方法有两种参数类型。
1. binarySearch(Object[],Object key)
import java.util.Arrays;
public class Reference {
public static void main(String[] args) {
int ia[]=new int[]{1,8,9,4,5};
Arrays.sort(ia); //对数组从小到大进行排序(Arrays的方法sort)
int index=Arrays.binarySearch(ia,4);
System.out.println("4的索引位置是:"+index);
}
}
binarySearch(Object[],int fromIndex,int toIndex,Object
key)
该方法在指定的范围内检索某一元素。public class Rakel { public static void main(String[] args) { String b[]=new String[]{“ab”,”cd”,”ef”,”yz”}; Arrays.sort(b); //对数组从小到大进行排序(Arrays的方法sort) int x=Arrays.binarySearch(b,0,2,”cd”); System.out.println(“cd的索引位置为:”+x); } }
- ### 数组排序算法
- #### 冒泡排序
- 冒泡排序的基本思想是**对比相邻的元素值**,如果满足条件就交换元素值,**把较小的元素移动到数组前面,把大的元素移动到数组后面**(也就是交换两个元素的位置),这样较小的元素就像气泡一样从底部上升到顶部。
- 冒泡算法由**双层循环**实现,其中**外层循环用于控制排序轮数**,一般为要排序的
数组长度减1次,因为最后一次循环只剩下一个数组元素,不需要对比,同时数组已
经完成排序了。而**内层循环主要用于对比数组中每个邻近元素的大小**,以确定是否
交换位置,对比和交换次数随排序轮数而减少。

- 实例代码:
public class BubbleSort { public static void main(String[] args) { //创建一个乱序的数组元素 int[] array={34,45,89,12,23,54,75}; //创建冒泡排序类的对象 BubbleSort sorter=new BubbleSort(); //调用排序方法将数组排序 sorter.sort(array); } /** * * @param array//要排序的数组 * */ public void sort(int[]array){ for (int i=1;i<array.length;i++){ //比较相邻两个元素,较大的数往后冒泡 for (int j=0;j<array.length-i;j++){ if (array[j] > array[j+1]){ int temp=array[j];//把第一个元素值保存到临时变量中 array[j]=array[j+1];//把第二个元素值保存到第一个元素单元中 array[j+1]=temp;//把临时变量(也就是第一个元素原值)保存到第二个元素中 } } } showArray(array); //输出冒泡排序后的数组元素 } /** * //显示数组中的所有元素 * @param array * */ public void showArray(int[]array){ for (int i:array){ //遍历数组 System.out.print(“>”+i); //输出每个数组元素值 } System.out.println(); } }
- #### 直接选择排序
- 直接选择排序方法属于选择排序的一种,它的排序速度要比冒泡排序快一些,也是常用的排序算法
- 直接选择排序的基本思想是将指定排序位置与其他数组元素分别对比,如果满足条件就交换元素值。注意这里与冒泡排序的区别,不是交换相邻元素,而是**把满足条件的元素与指定的排序位置交换**(如从最后一个元素开始排序),**这样排序好的位置逐渐扩大,最后整个数组都成为已排序好的格式**。
- 实例代码:
/** * * * */ public class Selectsort { public static void main(String[] args) { int[]array={1,32,45,36,67,89,12}; Selectsort sorter=new Selectsort(); sorter.sort(array); } /** * * @param array * */ public void sort(int[]array){ //调用上面sort方法及其变量 int index; for (int i=1;i<=array.length;i++){ index=0; for (int j=1;j<=array.length-i;j++){ if (array[j]>array[index]){ index=j; } } int temp=array[array.length-i]; array[array.length-i]=array[index]; array[index]=temp; } showArray(array); } /** * * * @param array * */ public void showArray(int[]array){ for (int i:array){ System.out.print(“>”+i);; } System.out.println(); } }
- #### 反转排序
- 反转排序就是以相反的顺序把原有数组的内容重新排序。
- 反转排序的基本思想比较简单,也很好理解,其实现思路就是把数组最后一个元素与第一个元素替换,倒数第二个元素与第二个元素替换,依此类推,直到把所有数组元素反转替换。
- 实例代码:
/** * * * */ public class ReverseSort { public static void main(String[] args) { int[] array={13,20,32,56,78,90}; ReverseSort sorter=new ReverseSort(); sorter.sort(array); } /** * * @param array * 要排序的数组 */ public void sort(int[]array) { System.out.println(“数组原有内容:”); showArray(array); int temp; int len=array.length; for (int i=0;i<len/2;i++){ temp=array[i]; array[i]=array[len-1-i]; array[len-1-i]=temp; } System.out.println(“数组反转后内容:”); showArray(array); } /** * * * @param array * 要显示的数组 */ public void showArray(int[]array){ for (int i:array){ System.out.println(“\t”+i); } System.out.println(); } }
- ### 类和对象
- #### 类
- 类是**封装对象的属性和行为的载体**,而在Java语言中对象的属性以**成员变量**的形式存在,对象的方法以**成员方法**的形式存在。
- **成员变量**
- 为了了解成员变量,首先定义一个图书类,成员变量对应于类对象的属性,在Book类中设置3个成员变量,分别为id、name和category,分别对应于图书编号、图书名称和图书类别3个图书属性。
- 实例代码:
public class book { private String name; //定义成员变量
public String getName(){ //定义成员方法
int id=0; //定义局部变量
setName("Java");
return id+this.name;
}
private void setName(String name){ //定义一个setName()成员方法
this.name=name;
}
public book getbook(){
return this;
} } ``` - **成员方法** - 定义成员方法的语法格式如下: ``` 权限修饰符 返回值类型 方法名(参数类型 参数名){ ...//方法体 return 返回值; } ``` - 一个成员方法可以有参数,这个参数可以是**对象**,也可以是**基本数据类型的变量**,同时成员方法有返回值和不返回任何值的选择,如果方法需要返回值,可以在方法体中使用`return`关键字,使用这个关键字后,方法的执行将被终止 - **权限修饰符** - Java中的权限修饰符主要包括`private`、`public`和`protected`,这些修饰符控制着对类和类的成员变量以及成员方法的访问。如果一个类的成员变量或成员方法被修饰为`private`,则该成员变量**只能在本类中被使用**,在**子类中是不可见的**,并且对其他包的类也是不可见的。如果将类的成员变量和成员方法的访问权限设置为`public`,那么除了可以在**本类使用这些数据之外,还可以在子类和其他包的类中使用**。如果一个类的访问权限被设置为`private`,**这个类将隐藏其内的所有数据,以免用户直接访问它**。如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为`public`访问权限。如果一个类使用`protected`修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和成员方法。 - **局部变量** - 如果在成员方法内定义一个变量,那么这个变量被称为局部变量。 - **局部变量的有效范围** - 可以将局部变量的有效范围称为**变量的作用域**,局部变量的有效范围从该变量的声明开始到该变量的结束为止。  - **`this`关键字** - 使用this关键字来代表本类对象的引用,this关键字被隐式地用于引用对象的成员变量和方法 - 事实上,this引用的就是本类的一个对象。在局部变量或方法参数覆盖了成员变量时,如上面代码的情况,就要添加this关键字明确引用的是类成员还是局部变量或方法参数。 - **类的构造方法** - 在类中除了成员方法之外,还存在一种特殊类型的方法,那就是构造方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。 - 构造方法**没有返回值**。 - 构造方法的名称要与**本类的名称相同**。 - #### 静态变量、常量和方法 - 由`static`修饰的变量、常量和方法被称作静态变量、常量和方法。 - 被声明为`static`的变量、常量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和“.”运算符调用静态成员。 - 对于静态方法(使用规则): - 在静态方法中不可以使用`this`关键字。 - 在静态方法中不可以直接**调用非静态方法**。 - 调用静态常量,变量以及方法的实例代码: ``` public class StaticTest {
static double PI=3.1456; //定义静态常量
static int id; //定义静态变量
public static void Method1(){ //在类中定义静态方法
}
public void Method2(){ //在类中定义一个非静态方法
System.out.println(StaticTest.PI); //调用静态常量
System.out.println(StaticTest.id); //调用静态变量
StaticTest.Method1(); //调用静态方法
} } ``` - #### 类的主方法 - 在主方法的定义中可以看到其具有以下特性: - **主方法是静态的**,所以如要直接在主方法中**调用其他方法,则该方法必须也是静态的**。 - 主方法**没有返回值**。 - 主方法的形参为数组。其中args[0]~args[n]分别代表程序的第一个参数到第n个参数,可以使用`args.length`获取**参数的个数**。 - #### 对象 - **对象的创建** - 准确地说,可以在Java语言中使用`new`操作符**调用构造方法创建对象**。  - **访问对象的属性和行为** - 如果希望成员变量不被其中任何一个对象改变,可以使用`static`关键字。 - 实例代码: ``` public class AccessProperty {
static int i=47; //定义静态成员变量
public void call(){ //定义成员方法
System.out.println("调用call()方法");
for(i=0;i<3;i++){
System.out.print(i+"");
if (i==2){
System.out.println("\n");
}
}
}
public AccessProperty(){ //定义构造方法
}
public static void main(String[] args) { //定义主方法
AccessProperty t1=new AccessProperty(); //创建一个对象
AccessProperty t2=new AccessProperty(); //创建另一个对象
t2.i=60;
//使用第一个对象调用类成员变量
System.out.println("第一个实例对象调用i变量的结果为:"+t1.i++);
t1.call();//使用第一个对象调用类成员方法
//使用第二个对象调用类成员变量
System.out.println("第二个实例对象调用i变量的结果为:"+t2.i);
t2.call();//使用第二个对象调用类成员方法
} } ```  从上述运行结果中可以看到,**由于使用t2.i=60语句改变了静态成员变量的值,使用对象t1调用成员变量的值也为60**,这正是**i值被定义为静态成员变量的效果**,即使使用两个对象对同一个静态成员变量进行操作,依然可以改变静态成员变量的值,因为在内存中两个对象同时指向同一块内存区域。`t1.i++`语句执行完毕后,i值变为3。当再次调用`call()`方法时又被重新赋值为0,做循环打印操作。 - #### 对象的引用 - 类名 对象引用名称 - 引用与对象相关联的语法如下: - `Book book=new Book();` - #### 对象的比较 - 在Java语言中有两种比较对象的方式,分别为`“==”`运算符与`equals()`方法。 - 实例代码: ``` public class Compare {
public static void main(String[] args) {
String c1=new String("abc"); //创建两个String型对象引用
String c2=new String("abc");
String c3=c1; //将c1对象引用赋予c3
System.out.println("c2==c3的运算结果为:"+(c2==c3));
System.out.println("c2.equals(c3)的运算结果为:"+(c2.equals(c3)));
} } ``` - 第一个:false 第二个:true - 从上述运行结果中可以看出,`“==”`运算符和`equals()`方法比较的内容是不相同的,`equals()`方法是`String`类中的方法,它**用于比较两个对象引用所指的内容是否相等**;而`“==”`运算符比较的是**两个对象引用的地址是否相等**。由于c1与c2是两个不同的对象引用,两者在内存中的位置不同,而`“String c3=c1;”`语句将c1的 引用赋给c3,所以c1与c3这两个对象引用是相等的,也就是打印c1==c3这样的语句将返回true值。 - ### 包装类 - #### Integer - `java.lang`包中的`Integer`类、`Long`类和`Short`类,可将基本类型`int、long`和`short`封装成一个类。 - 该类提供了多个方法,能在int类型和`String`类型之间互相转换,同时还提供了其他一些处理int类型时非常有用的常量和方法。 - *构造方法* - `Integer (int number)`
- 该方法以一个`int`型变量为参数来获取`Integer`对象
- 例:`Integer number = new Integer(7);` - `Integer (String str)`
- 该方法以一个`String`型变量为参数来获取`Integer`对象。
- 例:`Integer number = new Integer("45");`  - `Integer`类中的`parseInt()`方法返回与调用该方法的数值字符串相应的整型 `(int)`值。 - `Integer`类中的`parseInt()`方法返回与调用该方法的数值字符串相应的整型`(int)`值。 - 实例代码: ``` public class Summation {
public static void main(String[] args) {
String str[]={"23","43","56","67","78"};
int sum=0;
for (int i=0;i<str.length;i++){
int myint=Integer.parseInt(str[i]); //将数组中每个元素转换为int型
sum=sum+myint; //叠加
}
System.out.println("数组的元素之和为:"+sum);
} } ``` |方法|字符串类别| |:----:|:----:| |toString()|十进制字符串| |toBinaryString()|二进制字符串| |toHexString()|十六进制字符串| |toOctalString()|八进制字符串| - 实例代码: ``` ublic class Charac {
public static void main(String[] args) {
String str=Integer.toString(123);
String str2=Integer.toBinaryString(123);
String str3=Integer.toHexString(123);
String str4=Integer.toOctalString(123);
System.out.println("'123’的十进制表示为:"+str);
System.out.println("'123'的二进制表示为:"+str2);
System.out.println("'123'的十六进制表示为:"+str3);
System.out.println("'123'的八进制表示为:"+str4);
} } ``` - **常量** - `MAX_VALUE`:表示int类型可取的最大值,即${2}^{31}$-1。 - `MIN_VALUE`:表示int类型可取的最小值,即${-2}^{31}$。 - `SIZE`:用来以二进制补码形式表示int值的位数。 - `TYPE`:表示基本类型int的Class实例。 - #### Boolean - 一个`Boolean`类型的对象只包含一个类型为`boolean`的字段。此外,此类还为`boolean`和`String`的相互转换提供了许多方法,并提供了处理`boolean`时非常有用的其他一些常量和方法。 - *构造方法* - `Boolean(boolean value)`
- 该方法创建一个表示`value`参数的`Boolean`对象。
- 例:`Boolean b = new Boolean(true);` - `Boolean(String str)`
- 该方法以`String`变量作为参数创建`Boolean`对象。如果`String`参数不为`null`且在忽略大小写时等于true,则分配一个表示`true`值的Boolean对象,否则获得一个`false`值的Boolean对象。
- 以String为变量,例:`Boolean bool = new Boolean("ok");`  - #### Byte - 一个Byte类型的对象只包含一个类型为byte的字段。 - 该类还为`byte`和`String`的相互转换提供了方法,并提供了其他一些处理byte时非常有用的常量和方法。 - *构造方法* - `Byte(byte value)`
- 通过这种方法创建的`Byte`对象,可表示指定的`byte`值。
- 例:`byte mybyte = 45; Byte b = new Byte(mybyte);` - `Byte(String str)`
- 通过这种方法创建的`Byte`对象,可表示`String`参数所指示的`byte`值。
- `Byte mybyte = new Byte("12");`  - 常量同Integer型相同 - #### Character - `Character`类在对象中包装一个基本类型为`char`的值。一个Character类型的对象包含类型为char的单个字段。 - *构造方法* - `Character(char value)` - 该类的构造函数必须是一个`char`类型的数据。通过该构造函数创建的`Character`类对象包含由char类型参数提供的值。一旦Character类被创建,它包含的数值就不能改变了。 - 例:`Character mychar = new Character('s');`  - *常量* - `CONNECTOR_PUNCTUATION`:返回byte型值,表示`Unicode`规范中的常规类别`“Pc”`。 - `TITLECASE_LETTER`:返回`byte`型值,表示`Unicode`规范中的常规类别`“Lt”`。 - `UNASSIGNED`:返回`byte`型值,表示`Unicode`规范中的常规类别`“Cn”`。
Double
和Float
包装类是对double、float
基本类型的封装,它们都是Number
类的子类,又都是对小数进行操作,所以常用方法基本相同Double(double value)
:基于double
参数创建Double
类对象。Double(String str)
:构造一个新分配的Double
对象,表示用字符串表示的double
类型的浮点值。
常量
MAX_EXPONENT
:返回int
值,表示有限double
变量可能具有的最大指数。MIN_EXPONENT
:返回int
值,表示标准化double
变量可能具有的最小指数。NEGATIVE_INFINITY
:返回double
值,表示保存double
类型的负无穷大值的常量。POSITIVE_INFINITY
:返回double
值,表示保存double
类型的正无穷大值的常量。Number
是BigDecimal
、BigInteger
、Byte
、Double
、Float
、Integer
、Long
和Short
类的父类,Number
的子类必须提供将表示的数值转换为byte、double、float、int、long和short
的方法。
DecimalFormat
类(用于格式化数字)、Math
类(为各种数学计算提供了工具方法)、Random
类(为处理随机数问题提供了各种方法)、BigInteger
类与BigDecimal
类(为所有大数字的处理提供了相应的数学运算操作方法)。double
型和float
型数据。在Java中使用java.text.DecimalFormat
格式化数字DecimalFormat
是NumberFormat
的一个子类,用于格式化十进制数字。它可以将一些数字格式化为整数、浮点数、百分数等。通过使用该类可以为要输出的数字加上单位或控制数字的精度。一般情况下可以在实例化DecimalFormat
对象时传递数字格式,也可以通过DecimalFormat
类中的applyPattern()
方法来实现数字格式化。
Math
类,该类包括常用的数学运算方法,如三角函数方法、指数函数方法、对数函数方法、平方根函数方法等一些常用数学函数,除此之外还提供了一些常用的数学常量,如``PI、E`等。public static double sin(double a)
:返回角的三角正弦。public static double cos(double a)
:返回角的三角余弦。public static double tan(double a)
:返回角的三角正切。public static double asin(double a)
:返回一个值的反正弦。public static double acos(double a)
:返回一个值的反余弦。public static double toRadians(double angdeg)
:将角度转换为弧度。public static double toDegrees(double angrad)
:将弧度转换为角度。double
型的。将这些方法的参数的值设置为double
型是有一定道理的,参数以弧度代替角度来实现,其中1°等于π/180弧度,所以180°可以使用π弧度来表示。除了可以获取角的正弦、余弦、正切、反正弦、反余弦、反正切之外,Math类还提供了角度和弧度相互转换的方法toRadians()和toDegrees()
。但需要注意的是,角度与弧度的转换通常是不精确的。public static double exp(double a)
:用于获取e的a次方,即取eª。public static double log(double a)
:用于取自然对数,即取lna的值。public static double log10(double a)
:用于取底数为10的对数。public static double sqrt(double a)
:用于取a的平方根,其中a的值不能为负值。public static double cbrt(double a)
:用于取a的立方根。public static double pow(double a,double b)
:用于取a的b次方。public static double ceil(double a)
:返回大于等于参数的最小整数。public static double floor(double a)
:返回小于等于参数的最大整数。public static double rint(double a)
:返回与参数最接近的整数,如果两个同为整数且同样接近,则结果取偶数。public static int round(float a)
:将参数加上0.5后返回与参数最近的整数。public static long round(double a)
:将参数加上0.5后返回与参数最近的整数,然后强制转换为长整型。public static double max(double a,double b)
:取a与b之间的最大值。public static int min(int a,int b)
:取a与b之间的最小值,参数为整型。public static long min(long a,long b)
:取a与b之间的最小值,参数为长整型。public static float min(float a,float b)
:取a与b之间的最小值,参数为浮点型。public static double min(double a,double b)
:取a与b之间的最小值,参数为双精度型。public static long abs(long a)
:返回长整型参数的绝对值。public static float abs(float a)
:返回浮点型参数的绝对值。public static double abs(double a)
:返回双精度型参数的绝对值。Math
类的random()
方法生成随机数和调用Random
类生成各种数据类型的随机数。Math
类中存在一个random()
方法,用于产生随机数字。这个方法默认生成大于等于0.0且小于1.0的double
型随机数,即0<=Math.random()<1.0
。虽然Math.random()
方法只可以产生0~1之间的double
型数字,但只要在Math.random()
语句上稍加处理,就可以使用这个方法产生任意范围的随机数
(char)(cha1+Math.random()*(cha2-cha1+1))
(重点:该随机数表达范围为≥cha1而<cha2)public class MathRandomChar {
public static char GetRandomchar(char cha1,char cha2){
return(char)(cha1+Math.random()*(cha2-cha1+1));
}
public static void main(String[] args) {
System.out.println("'a'到'z'字符之间任意一个:"+GetRandomchar('a','z'));
System.out.println("'A'到'Z'字符之间任意一个:"+GetRandomchar('A','Z'));
System.out.println("'0'到'9'数字字符之间任意一个:"+GetRandomchar('0','9'));
}
}
Math
类中的random()
方法可以获取随机数之外,Java中还提供了一种可以获取随机数的方式,那就是java.util.Random
类。通过实例化一个Random
对象可以创建一个随机数生成器。Random r=new Random(); //定义一个随机数对象
Random
类中提供了获取各种数据类型随机数的方法:
public int nextInt()
:返回一个随机整数。public int nextInt(int n)
:返回大于等于0且小于n的随机整数。public long nextLong()
:返回一个随机长整型值。public boolean nextBoolean()
:返回一个随机布尔型值。public float nextFloat()
:返回一个随机浮点型值。public double nextDouble()
:返回一个随机双精度型值。public double nextGaussian()
:返回一个概率密度为高斯分布的双精度值。java.math.BigInteger
类与java.math.BigDecimal
类。这两个类用于高精度计算,其中BigInteger
类是针对大整数的处理类,而BigDecimal
类则是针对大小数的处理类。BigInteger
类型的数字范围较Integer
类型的数字范围要大得多。前文介绍过Integer
是int的包装类,int的最大值为${2}^{31}$-1,如果要计算更大的数字,使用Integer数据类型就无法实现了,所以Java中提供了BigInteger
类来处理更大的数字。BigInteger
支持任意精度的整数,也就是说,在运算中BigInteger类型可以准确地表示任何大小的整数值而不会丢失信息。public BigInteger add(BigInteger val)
:做加法运算。public BigInteger subtract(BigInteger val)
:做减法运算。public BigInteger multiply(BigInteger val)
:做乘法运算。public BigInteger divide(BigInteger val)
:做除法运算。public BigInteger remainder(BigInteger val)
:做取余操作。public BigInteger[] divideAndRemainder(BigInteger val)
:用数组返回余数和商,结果数组中第一个值为商,第二个值为余数public BigInteger pow(int exponent)
:进行取参数的exponent
次方操作。public BigInteger negate()
:取相反数。public BigInteger shiftLeft(int n)
:将数字左移n位,如果n为负数,做右移操作。public BigInteger shiftRight(int n)
:将数字右移n位,如果n为负数,做左移操作。public BigInteger and(BigInteger val)
:做与操作。public BigInteger or(BigInteger val)
:做或操作。public int compareTo(BigInteger val)
:做数字比较操作。public boolean equals(Object x)
:当参数x是BigInteger类型的数字并且数值相等时,返回true
。public BigInteger min(BigInteger val)
:返回较小的数值。public BigInteger max(BigInteger val)
:返回较大的数值。BigDecimal
和BigInteger
都能实现大数字的运算,不同的是BigDecimal
加入了小数的概念。一般的float
型和double
型数据只可以用来做科学计算或工程计算,但由于在商业计算中要求数字精度比较高,所以要用到java.math.BigDecimal
类。BigDecimal
类支持任何精度的定点数,可以用它来精确计算货币值。public BigDecimal(double val)
:实例化时将双精度型转换为BigDecimal
类型。public BigDecimal(String val)
:实例化时将字符串形式转换为BigDecimal
类型。BigDecimal
类中实现加、减、乘、除的方法。
public BigDecimal add(BigDecimal augend)
:做加法操作。public BigDecimal subtract(BigDecimal subtrahend)
:做减法操作。public BigDecimal multiply(BigDecimal multiplicand)
:做乘法操作。public BigDecimal divide(BigDecimal divisor,int scale,introundingMode)
:做除法操作,方法中3个参数分别代表除数、商的小数点后的位数、近似处理模式。
public class BigDecimalDemo { static final int location=10; /** * 定义加法方法,参数为加数与被加数 * * @param value1 * 相加的第一个数 * @param value2 * 相加的第二个数 * @return 两数之和 */ public BigDecimal add(double value1,double value2){ BigDecimal b1=new BigDecimal(Double.toString(value1)); BigDecimal b2=new BigDecimal(Double.toString(value2)); return b1.add(b2);//调用加法方法 } /** * 定义减法方法,参数为减数与被减数 * @param value1 被减数 * * @param value2 减数 * * @return 两数之差 */ public BigDecimal sub(double value1,double value2){ BigDecimal b1=new BigDecimal(Double.toString(value1)); BigDecimal b2=new BigDecimal(Double.toString(value2)); return b1.subtract(b2);//调用减法方法 } /** * 定义乘法方法,参数为乘数与被乘数 * * @param value1 * 第一个乘数 * @param value2 * 第二个乘数 * @return */ public BigDecimal mul(double value1,double value2){ BigDecimal b1=new BigDecimal(Double.toString(value1)); BigDecimal b2=new BigDecimal(Double.toString(value2)); return b1.multiply(b2); // 调用乘法方法 } /** * 定义除法方法,参数为除数与被除数 * * @param value1 被除数 * * @param value2 除数 * * @return * */ public BigDecimal div(double value1,double value2){ return div(value1,value2,location);//调用自定义除法方法 } //定义除法方法,将参数分别位除数与被除数以及商小数点后的位数 public BigDecimal div(double value1,double value2,int b){ if (b<0){ System.out.println(“b的值必须大于等于0”); } BigDecimal b1=new BigDecimal(Double.toString(value1)); BigDecimal b2=new BigDecimal(Double.toString(value2)); //调用除法方法,商小数点后保留b位,并将结果进行四舍五入操作 return b1.divide(b2,b,BigDecimal.ROUND_HALF_UP);//调用除法方法 } public static void main(String[] args) { BigDecimalDemo b=new BigDecimalDemo(); System.out.println(“两个数字相加的结果为:”+b.add(-8.0,9.4)); System.out.println(“两个数字相减的结果为:”+b.sub(-8.0,9.4)); System.out.println(“两个数字相乘的结果为:”+b.mul(-8.0,9.4)); System.out.println(“两个数字相除结果,结果小数后保留10位:”+b.div(10,2)); System.out.println(“两个数字相除,保留小数后5位:”+b.div(-8.0,9.4,5)); } }
### 类的高级特性
- #### 导入包
- 使用`import`关键字导入包
- import关键字的语法如下:
import com.lzw.*; //指定com.lzw包中的所有类中的程序都能使用 import com.lzw.Math //指定com.lzw包中的Math类在程序中可以使用
- 在使用`import`关键字时,可以指定类的完整描述,如果为了使用包中更多的类,可以在使用`import`关键字指定时在包指定后加上*,这表示可以在程序中使用包中的所有类。
- 使用import导入静态成员
- 使用import导入静态成员的语法如下:
import static 静态成员
- 实例代码:
import static java.lang.Math.max; import static java.lang.System.out; public class ImportTest { public static void main(String[] args) { out.println(“5和7比较大小:”+max(5,7)); } }
### 异常处理
- 异常分为两大类:已检查和未检查
- 对于未检查异常也叫RunTimeException

- #### 捕捉异常
- Java语言的异常捕获结构由`try`、`catch`和`finally` 3部分组成。其中,`try`语句块存放的是可能发生异常的Java语句;`catch`程序块在`try`语句块之后,用来激发被捕获的异常;`finally`语句块是**异常处理结构的最后执行部分**,**无论`try`语句块中的代码如何退出**,都将执行`finally`语句块。
- **`try-each`语句**
- 实例代码:
public class Take { public static void main(String[] args) { try { //try语句中包含可能出现异常的程序代码 String str = “Ally”; System.out.println(str + “年龄是:”); int age = Integer.parseInt(“20L”); //数据类型转换 System.out.println(age); } catch (Exception e) { //catch语句用来获取异常信息 e.printStackTrace(); //输出异常性质 } System.out.println(“Program over”); } }
- 注意:
- `Exception`是`try`代码块传递给catch代码块的变量类型,`e`是变量名。`catch`代码块中语句`“e.getMessage();”`用于输出错误性质。通常,异常处理常用以下3个函数来获取异常的有关信息。
- `getMessage()`函数:输出错误性质.
- `toString()`函数:给出异常的类型与性质。
- `printStackTrace()`函数:指出异常的类型、性质、栈层次及出现在程序中的位置。
- **`finally`语句块**
- 完整的异常处理语句一定要包含`finally`语句,无论程序中有无异常发生,并且无论之间的`try-catch`是否顺利执行完毕,都会执行`finally`语句。
- #### 常见异常

- #### 自定义异常
- 在程序中使用自定义异常类,大体可分为以下几个步骤:
- 创建自定义异常类。
- 在方法中通过`throw`关键字抛出异常对象。
- 如果在当前抛出异常的方法中处理异常,可以使用`try-catch`语句块捕获并处理,否则在方法的声明处通过`throws`关键字指明要抛出给方法调用者的异常,继续进行下一步操作。
- 在出现异常方法的调用者中捕获并处理异常。
- 实例代码:
public class MyException extends Exception{ public MyException(String ErrorMessage){ super(ErrorMessage); } } public class Tran { static int avg(int number1,int number2)throws MyException{ if (number1<0||number2<0){ throw new MyException(“不可以小于0”); } if (number1>100||number2>100){ throw new MyException(“数值过于大了”); } return (number1+number2)/2; }
public static void main(String[] args) {
try{
int result=avg(-1,103);
System.out.println(result);
}catch (MyException e){
System.out.println(e);
}
} } ``` - 字符串`ErrorMessage`是要输出的错误信息。若想抛出用户自定义的异常对象,要使用`throw`关键字 - #### 在方法中抛出异常 - 若某个方法可能会发生异常,但不想在当前方法中处理这个异常,则可以使用`throws`、`throw`关键字在方法中抛出异常。 - **使用`throws`关键字抛出异常** - 实例代码: ``` public class Shoot {
static void pop() throws NegativeArraySizeException{ //定义方法并抛出NegativeArraySizeException异常
int arr[]=new int[-3]; //创建数组
}
public static void main(String[] args) {
try { //try语句处理异常信息
pop(); //调用pop()方法
}catch (NegativeArraySizeException e){
System.out.println("pop()方法抛出的异常");
}
} } ``` - **使用`throw`关键字抛出异常** - `throw`关键字通常用于方法体中,并且抛出一个异常对象。程序在执行到`throw`语句时立即终止,它后面的语句都不执行。通过`throw`抛出异常后,如果想在上一级代码中来捕获并处理异常,则需要在抛出异常的方法中使用`throws`关键字在方法的声明中指明要抛出的异常;如果要捕捉`throw`抛出的异常,则必须使用`try-catch`语句块。 - 实例代码: ``` public class MyException2 extends Exception{ //创建自定义异常类
String message; //定义String类型变量
public MyException2(String ErrorMessage){ //父类方法
message = ErrorMessage;
}
public String GetMessage(){ //覆盖父类方法
return message;
} } public class Captor {
static int quotient(int x,int y)throws MyException2{ //定义方法中抛出异常
if (y<0){ //判断参数是否小于0
throw new MyException2("除数不能是负数"); //异常信息
}
return x/y; //返回值
}
public static void main(String[] args) {
try {
int result=quotient(4,-3);
}catch (MyException2 e){
System.out.println(e.GetMessage());
}catch (ArithmeticException e){
System.out.println("除数不能为0");
}catch (Exception e){
System.out.println("程序发生了其他的异常");
}
} } ``` - #### 三种类型的异常处理 - 声明异常 - 抛出异常 - 捕获异常 - #### 运行时异常 - `RuntimeException`异常是程序运行过程中产生的异常。Java类库的每个包中都定义了异常类,所有这些类都是`Throwable`类的子类。`Throwable`类派生了两个子类,分别是`Exception`和`Error`类。`Error`类及其子类用来描述Java运行系统中的内部错误以及资源耗尽的错误,这类错误比较严重。`Exception`类称为**非致命性类**,可以通过捕捉处理使程序继续执行。`Exception`类又根据错误发生的原因分为`RuntimeException`异常和除`RuntimeException`之外的异常
Object
:所有类的超类(hash code)
是由对象导出的一个整型值。散列码是没有规律的。如果 x 和 y 是两个不同的对象, x.hashCode( )
与 y.hashCode( )
基本上不会相同。hashCode
方法定义在Object
类中, 因此每个对象都有一个默认的散列码,其值为对象的存储地址。public class test {
public static void main(String[] args) {
String r="HELLO";
StringBuilder rb=new StringBuilder(r);
System.out.println(r.hashCode()+" "+rb.hashCode());
String m=new String("HELLO");
StringBuilder mb=new StringBuilder(m);
System.out.println(m.hashCode()+" "+mb.hashCode());
}
}
StringBuffer
类中没有定义hashCode
方法,它的散列码是由Object
类的默认hashCode
方法导出的对象存储地址。Objects.hash
并提供多个参数。这个方法会对各个参数调用Objects.hashCode
,并组合这些散列值。public int hashCode{
return Objects.hash(name, salary, hireDay);
}
Equals
与 hashCode
的定义必须一致:如果 x.equals(y)
返回 true
, 那么 x.hashCode( )
就必
须与 y.hashCode( )
具有相同的值。Arrays.hashCode
方法计算一个散列码,这个散列码由数组元素的散列码组成。
toString
方法,并将子类域的描述添加进去。如果超类使用了 getClass( ).getName( )
, 那么子类只要调用 super.toString( )
就可以了。ArrayList
是一个采用类型参数(type parameter) 的泛型类( generic class)。ArrayList<> staff = new ArrayList<>(); //也可添加初始容量
add
方法可以将元素添加到数组列表中。
staff.add(new Employee("Harry Hacker", • • •));
staff.add(new Eraployee("Tony Tester", . . .));
ensureCapacity
方法:
staff.ensureCapacity(数量)
new ArrayList<>(lOO) // capacity是返回字符串所占容器的总大小
new Employee[100] // size is 100 数组的大小
size
方法将返回数组列表中包含的实际元素数目。例如,staff.size
将返回 staff
数组列表的当前元素数量, 它等价于数组 a 的a.length
。
public
interface
接口名 //不要在定义接口的时候使用 final
关键字,也不可使用private
,protected
修饰符public
class
类名 implements
接口名public static final
(常量),所以其值无法改变。``` interface Happy{ void Happy(); } interface Pretty{ void Pretty(); } interface Extroverted{ void Extroverted(); }
public class Girl implements Happy,Pretty,Extroverted{ @Override public void Happy(){ System.out.println(“开心的女孩”); }
@Override
public void Pretty() {
System.out.println("漂亮的女孩");
}
@Override
public void Extroverted() {
System.out.println("外向的女孩");
} } ``` - 女孩类引用三个定义的接口并使用它们包含的方法,从而实现多重继承 - #### 实现多态 - 多态可以通过继承(`extends`)的关系实现,也可以通过接口的形式实现。 - 其实将父类对象应用于子类的特征就是多态。(将子类的对象看作为父类的实例化对象,即可调用父类的方法进而实现子类所需要) - `Override`(方法覆盖)与`Overload`(方法重载)之间的区别:重载`Overload`表示同一个类中可以有多个名称相同的方法,但这些方法的参数列表各不相同(即参数个数或类型不同),而`Override`不仅名称相同,参数列表也相同。 - 实例代码: ``` public interface Shape { //Shape接口表示一个形状
String name(); } public class Circle implements Shape { //Circle 类实现了 Shape 接口,并重写了 name() 方法。
@Override
public String name() {
return "圆";
} } public class Square implements Shape { //Square 类也实现了 Shape 接口,并重写了 name() 方法。
@Override
public String name() {
return "正方形";
} } List<Shape> shapes = new ArrayList<>(); //测试类 Shape circleShape = new Circle(); Shape squareShape = new Square();
shapes.add(circleShape); shapes.add(squareShape);
for (Shape shape : shapes) { System.out.println(shape.name()); }
public class test2 { interface Coach { void Command(); }
interface CoachFactory {
Coach CreateCoach();
}
static class ACoach implements Coach {
public void Command() {
System.out.println("我是A级证书教练,其他都给我衮");
}
}
static class ACoachFactory implements CoachFactory {
public Coach CreateCoach() {
return new ACoach();
}
}
static class CCoach implements Coach {
public void Command() {
System.out.println("我是C级教练");
}
static class CCoachFactory implements CoachFactory {
@Override
public Coach CreateCoach() {
return new CCoach();
}
}
public class Demo {
public static void create(CoachFactory factory) {
factory.CreateCoach().Command();
}
public static void main(String[] args) {
create(new ACoachFactory());
create(new CCoachFactory());
}
}
} } ``` - ### 封装 - 指利用抽象将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。 - 将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节。 - 实例代码: ``` public class Husband { /*
* 对属性的封装
* 一个人的姓名、性别、年龄、妻子都是这个人的私有属性
*/
private String name;
private String sex;
private int age;
private Wife wife;
/*
* setter()、getter()是该对象对外开发的接口
*/
public String getName(){
return name;
}
public String setName(String name){
this.name=name;
}
public String getSex(){
return sex;
}
public String setSex(String sex){
this.sex=sex;
}
public int getAge() {
return age;
}
public int setAge(){
this.age=age;
}
public void setWife(Wife wife) {
this.wife=wife;
} } ``` - 封装确实可以使我们更容易地修改类的内部实现,而无需修改使用了该类的代码。 - 封装可以对成员变量进行更精确的控制。 - ### lambda 表达式 - 一种 `lambda` 表达式形式:参数, 箭头(->) 以及一个表达式。如果代码要完成的计算无法放在一个表达式中,就可以像写方法一样,把这些代码放在 {}中, 并包含显式的 `return`语句 ``` (String first, String second) -> //()内为参数 { //需要完成的计算代码 if (first.length() < second.length()) return -1; else if (first.length() > second.length()) return 1; else return 0; } ``` - 即使 lambda 表达式**没有参数**, 仍然要提供空括号,就像无参数方法一样: ``` () -> { for(i=0,i<=100,i++)System.out.println(i); } ``` - ### 枚举类 - 枚举类型下的实例对象是其类所包含(拥有)的 - 若你创建了Season这个类,那么其下就有春(SPRING),夏(SUMMER),秋(AUTUMN),冬(WINTER),便要维护他们。 ``` enum SeasonEnum{ //枚举季节类
SPRING("春天"),SUMMER("夏天"),AUTUMN("秋天"),WINTER("冬天");
private String chinese;
SeasonEnum(String chinese){ //构造方法
this.chinese=chinese; //调用this关键字
}
public String getchinese(){
return chinese;
} } public class Test {
public static void main(String[] args) {
String summer = "SUMMER";
SeasonEnum season1 = SeasonEnum.SPRING;
System.out.println(season1.getchinese());
} } ``` ``` enum SeasonEnum{ //枚举季节类
SPRING,SUMMER,AUTUMN,WINTER; } public class Test {
public static void main(String[] args) {
String summer="SUMMER";
SeasonEnum season1=SeasonEnum.valueOf(summer); //使用valueOf,获取SUMMER的枚举类型
SeasonEnum season2=SeasonEnum.SPRING; //直接初始化
switch (season1){
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
}
} } ```
Collection
接口是层次结构中的根接口。构成Collection
的单位称为元素。Collection
接口通常不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。由于List
接口与Set
接口都继承了Collection
接口,因此这些方法对List
集合与Set
集合是通用的。
public class p2 {
public static void main(String[] args) {
Collection <String>list=new ArrayList<>(); //实例化集合类对象
list.add("地平线"); //向集合添加数据
list.add("班加罗尔");
list.add("直布罗陀");
list.add("亡灵");
Iterator<String> it=list.iterator(); //创建迭代器
while (it.hasNext()){ //判断是否有下一个元素
String apex=(String)it.next(); //获取集合中元素
System.out.println(apex);
}
}
}
List
集合包括List
接口以及List
接口的所有实现类。List
集合中的元素允许重复,各元素的顺序就是对象插入的顺序。类似Java数组,用户可通过使用索引(元素在集合中的位置)来访问集合中的元素。List
接口
get(int index)
;获得指定索引位置。set(int index,Object obj)
;将集合中指定索引位置的对象修改为指定对象。ArrayList
和LinkedList
。
ArrayList
类实现了可变的数组,允许保存所有元素,包括null,并可以根据索引位置对集合进行快速的随机访问;缺点是向指定的索引位置插入对象或删除对象的速度较慢。LinkedList
类采用链表结构保存对象。这种结构的优点是便于向集合中插入和删除对象,需要向集合中插入、删除对象时,使用LinkedList
类实现的List
集合的效率较高;但对于随机访问集合中的对象,使用LinkedList
类实现List
集合的效率较低。List<E> list=new ArrayList<>();
,其中E为数据类型,比如String。Set
集合中的对象不按特定的方式排序,只是简单地把对象加入集合中,但Set
集合中不能包含重复对象。Set
集合由Set
接口和Set
接口的实现类组成。Set
接口继承了Collection
接口,因此包含Collection
接口的所有方法。HashSet
类与Treeset
类。
HashSet
类实现Set
接口,由哈希表(实际上是一个HashMap
实例)支持。它不保证Set
的迭代顺序,特别是它不保证该顺序恒久不变。此类允许使用null
元素。TreeSet
类不仅实现了Set
接口,还实现了java.util.SortedSet
接口,因此,TreeSet
类实现的Set
集合在遍历集合时按照自然顺序递增排序,也可以按照指定比较器递增排序,即可以通过比较器对用TreeSet
类实现的Set
集合中的对象进行排序。
TreeSet
类实现的Set
集合必须实现Comparable
接口,该接口中的compareTo(Object o)
方法比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、0或正整数。Map
集合没有继承Collection
接口,其提供的是key
到value
的映射。Map
中不
能包含相同的key
,每个key
只能映射一个value
。key
还决定了存储对象在映射中的存储位置,但不是由key
对象本身决定的,而是通过一种“散列技术”进行处理,产生一个散列码的整数值。散列码通常用作一个偏移量,该偏移量对应分配给映射的内存区域的起始位置,从而确定存储对象在映射中的存储位置。Map
集合包括Map
接口以及Map
接口的所有实现类。
public class p3 {
public static void main(String[] args) {
Map<String,String>map=new HashMap<>();
map.put("01","atree");
map.put("02","point");
map.put("03","truth");
map.put("04","coace");
Set<String>set=map.keySet();
Iterator<String>it= set.iterator();
System.out.println("key集合中的所有元素:");
while (it.hasNext()){
System.out.println(it.next());
}
Collection<String>collection=map.values();
it=collection.iterator();
System.out.println("values集合中的元素:");
while (it.hasNext()){
System.out.println(it.next());
}
}
}
Map
接口常用的实现类有HashMap
和TreeMap
。建议使用HashMap
类实现Map
集合,因为由HashMap
类实现的Map
集合添加和删除映射关系效率更高。HashMap
是基于哈希表的Map
接口的实现,HashMap
通过哈希码对其内部的映射关系进行快速查找;而TreeMap
中的映射关系存在一定的顺序,如果希望Map
集合中的对象也存在一定的顺序,应该使用TreeMap
类实现Map
集合。HashMap
类是基于哈希表的Map
接口的实现,此实现提供所有可选的映射操作,并允许使用null
值和null
键,但必须保证键的唯一性。HashMap
通过哈希表对其内部的映射关系进行快速查找。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。TreeMap
类不仅实现了Map
接口,还实现了java.util.SortedMap
接口,因此,集合中的映射关系具有一定的顺序。但在添加、删除和定位映射关系时,TreeMap
类比HashMap
类性能稍差。由于TreeMap
类实现的Map
集合中的映射关系是根据键对象按照一定的顺序排列的,因此不允许键对象是null
。Input/Output
,输入/输出)流提供了一条通道程序,可以使用这条通道把
源中的字节序列送到目的地。虽然I/O流通常与磁盘文件存取有关,但是程序的源和
目的地也可以是键盘、鼠标、内存或显示器窗口等。
InputStream
(字节输入流)或抽
象类Reader
(字符输入流)的子类;而所有输出流都是抽象类OutputStream
(字
节输出流)或抽象类Writer
(字符输出流)的子类。InputStream
类是字节输入流的抽象类,是所有字节输入流的父类。该类中所有方法遇到错误时都会引发IOException
异常。read()
方法:从输入流中读取数据的下一个字节。返回0~255范围内的int
字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为-1。read(byte[] b)
:从输入流中读入一定长度的字节,并以整数的形式返回字节数。mark(int readlimit)
方法:在输入流的当前位置放置一个标记,readlimit
参数告知此输入流在标记位置失效之前允许读取的字节数。reset()
方法:将输入指针返回到当前所做的标记处。skip(long n)
方法:跳过输入流上的n个字节并返回实际跳过的字节数。markSupported()
方法:如果当前流支持mark()/reset()
操作就返回true
。close
方法:关闭此输入流并释放与该流关联的所有系统资源。
Unicode
编码,是双字节的。InputStream
是用来处理字节的,并不适合处理字符文本。Java为字符文本的输入专门提供了一套单独的类Reader
,但Reader
类并不是InputStream
类的替换者,只是在处理字符串时简化了编程。Reader
类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。
OutputStream
类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。
OutputStream
类中的所有方法均返回void,在遇到错误时会引发IOException
异常。write(int b)
方法:将指定的字节写入此输出流。write(byte[] b)
方法:将b个字节从指定的byte
数组写入此输出流。write(byte[] b,int off,int len)
方法:将指定byte
数组中从偏移量off
开始的len
个字节写入此输出流。flush()
方法:彻底完成输出并清空缓存区。close()
方法:关闭输出流。Writer
类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。
File
类是java.io
包中唯一代表磁盘文件本身的对象。File
类定义了一些与平台无关的方法来操作文件,可以通过调用File
类中的方法,实现创建、删除、重命名文件等操作。File
类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件读写权限等。数据流可以将数据写入到文件中,文件也是数据流最常用的数据媒体。File(String pathname)
语法如下:new file(String pathname)
其中,pathname
指路径名称(包含文件名)。例如:File file = new File("d:/1.txt");
File(String parent,String child)
该构造方法根据定义的父路径和子路径字符串(包含文件名)创建一个新的File
对象。语法如下:new File(String parent,String child)
File(File f , String child)
该构造方法根据parent
抽象路径名和child
路径名字符串创建一个新File
实例。语法如下:new File(File f,String child)
public class p5 {
public static void main(String[] args) {
File file=new File("word.txt");
if (file.exists()){
file.delete();
System.out.println("文件已删除");
}else {
try { //捕获可能出现的异常
file.createNewFile(); //创建该文件
System.out.println("文件已创建");
} catch (Exception e){
e.printStackTrace();
}
}
}
}
public class p6 {
public static void main(String[] args) {
File file = new File("word.txt");
if (file.exists()) {
String filename=file.getName();
long lenth=file.length();
boolean hidden=file.isHidden();
System.out.println("文件名称为:"+filename);
System.out.println("文件长度为:"+lenth);
System.out.println("文件是否为隐藏文件:"+hidden);
}else {
System.out.println("文件不存在");
}
}
}
FileInputStream
类与FileOutputStream
类都用来操作磁盘文件。如果用户的文件读取需求比较简单,则可以使用FileInputStream
类,该类继承自InputStream
类。FileOutputStream
类与FileInputStream
类对应,提供了基本的文件写入能力。FileOutputStream
类是OutputStream
类的子类。
public class p7 {
public static void main(String[] args) {
File file=new File("word.txt");
try {
FileOutputStream outputStream=new FileOutputStream(file);
byte buy[]="玩APEX就应该享受,我也在享受,谁不在享受,享受就得应该享受,而不是不享受。".getBytes();
outputStream.write(buy);
outputStream.close();
}catch (Exception e){
e.printStackTrace();
}
try {
FileInputStream inputStream=new FileInputStream(file);
byte byt[]=new byte[1024]; //[]为数组大小,byte为字节数组
int len=inputStream.read(byt);
System.out.println("文件中的信息为:"+new String(byt,0,len));
inputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
FileReader
和FileWriter
类
FileOutputStream
类向文件中写入数据与使用FileInputStream
类从文件中将内容读出来,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流Reader
或Writer
类即可避免这种现象。FileReader
和FileWriter
字符流对应了FileInputStream
和FileOutputStream
类。FileReader
流顺序地读取文件,只要不关闭流,每次调用read()
方法就顺序地读取源中其余的内容,直到源的末尾或流被关闭。skip()
、mark()
和reset()
方法都成为可能。BufferedInputStream
与BufferedOutputStream
类BufferedInputStream
类可以对所有InputStream
类进行带缓存区的包装以达到性能的优化。BufferedInputStream
类有两个构造方法:
BufferedInputStream(InputStream in)
。BufferedInputStream(InputStream in,int size)
。BufferedInputStream
对象位于InputStream
类对象之前。
BufferedReader
与BufferedWriter
类
Reader
和Writer
类。其具有内部缓存机制,可以以行为单位进行输入\输出。
public class p6 {
public static void main(String[] args) {
String content[]={"Hi 好久不见","你过得还好吗?","我想你了","不是你不在我身边了,而感到寂寞","是因为我真的爱上你了","回来吧。"};
File file=new File("word.txt");
try {
FileWriter fileWriter=new FileWriter(file);
BufferedWriter buf=new BufferedWriter(fileWriter);
for (int k = 0; k<content.length; k++){
buf.write(content[k]);
buf.newLine();
}
buf.close();
fileWriter.close();
}catch (Exception e){
e.printStackTrace();
}
try {
FileReader fileReader=new FileReader(file);
BufferedReader bufr=new BufferedReader(fileReader);
String s=null;
int i=0;
while ((s=bufr.readLine())!=null){
i++;
System.out.println("第"+i+"行:"+s);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
DataInputStream
类与DataOutputStream
类)允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。writeBytes
只是将字符串中的每一个字符的低字节内容写入目标设备中;而writeChars
将字符串中的每一个字符的两个字节的内容都写到目标设备中;writeUTF
将字符串按照UTF
编码后的字节长度写入目标设备,然后才是每一个字节的UTF
编码。DataInputStream
类只提供了一个readUTF()
方法返回字符串。这是因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束。ZipOutputStream
与ZipInputStream
类来实现文件的压缩/解压缩。无论是从ZIP压缩文件中读取内容还是写入内容进ZIP文件中都是先找到”目录进入点”。集合类型 | 描述 |
---|---|
ArrayList | 一种可以动态增长和缩减的索引序列 |
LinkedList | 一种可以在任何位置进行高效地插人和删除操作的有序序列 |
ArrayDeque | 一种用循环数组实现的双端队列 |
HashSet | 一种没有重复元素的无序集合 |
TreeSet | 一种有序集 |
EnumSet | 一种包含枚举类型值的集 |
LinkedHashSet | 一种可以记住元素插人次序的集 |
PriorityQueue | 一种允许高效删除最小元素的集合 |
HashMap | 一种存储键/值关联的数据结构 |
TreeMap | 一种键值属于枚举类型的映射表 |
EnumMap | 一种键值属于枚举类型的映射表 |
LinkedHashMap | 一种可以记住键 / 值项添加次序的映射表 |
WeakHashMap | 一种其值无用武之地后可以被垃圾回收器回收的映射表 |
IdentityHashMap | 一种用==而不是equals()来比较键的映射表 |
操作系统中的多任务(multitasking):在同一刻运行多个程序的能力
多线程程序在较低的层次上扩展了多任务的概念:一个程序同时执行多个任务。通常,每一个任务称为一个线程(thread), 它是线程控制的简称。可以同时运行一个以上线程的程序称为多线程程序(multithreaded)。
线程:进程中的单个顺序控制流,是一条执行路径
线程全生命周期
实现Runnable
接口的方式:
MyRunnable
,实现Runnable
接口run()
方法,在run()
方法中定义线程要执行的任务。MyRunnable
类的实例,并将其作为参数传递给Thread
类的构造器。Thread
类的对象,把MyRunnable
对象作为构造方法的参数调用Thread
类的start()
启动线程,执行run()
方法
Thread.MIN_PRIORITY
) - 10 (Thread.MAX_PRIORITY
)。Thread类中的方法:
wait()、notify()和notifyAll()
方法是本地方法,并且为final方法,无法被重写。wait()
方法使得线程暂停(线程阻塞),并且当前线程必须拥有此对象的monitor
(即锁),直到其他线程调用notify()
或notifyAll()
方法唤醒它。notify()
方法能够唤醒一个正在等待这个对象的monitor
的线程,如果有多个线程都在等待这个对象的monitor
,则只能唤醒其中一个notifyAll()
方法能够唤醒所有正在等待这个对象的monitor
wait()
方法,当前线程必须拥有这个对象的monitor
(即锁),因此调用wait()
方法必须在同步块或者同步方法中进行(synchronized
块或者synchronized
方法)notify()
和notifyAll()
方法只是唤醒等待该对象的monitor
的线程,并不决定哪个线程能够获取到monitor
await()
和signal()
方法Condition
依赖于Lock
接口,生成一个Condition
的基本代码是lock.newCondition()
Condition
的await()
和signal()
方法,都必须在lock
保护之内,就是说必须在lock.lock()
和lock.unlock
之间才可以使用Conditon
中的await()
对应Object
的wait()
;Condition
中的signal()
对应Object
的notify()
;Condition
中的signalAll()
对应Object
的notifyAll()
.从线程同步上来看,无论synchronized
还是Lock
,他们的底层都是通过传入唯一的锁对象来实现线程同步的。
从线程通信来看,synchronized
的线程只能实现两个线程之间的通信,但是Condition
却可以实现更多线程之间的通信。
原子性操作具有不可分割性
非原子操作都会存在线程安全问题,需要我们使用同步技术(sychronized
)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性
volatile
关键字是一种类型修饰符,被它声明的类型变量表示可以被某些编译器未知的因素更改
int volatile vint;
被关键字volatile修饰后:
Executor
框架
Executor
来启动线程比使用 Thread
的 start
方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免 this
逃逸问题。Executor
框架不仅包括了线程池的管理,还提供了线程工厂、队列以及拒绝策略等Runnable /Callable
)
Runnable
接口(无返回值) 或 Callable
接口(有返回值)。Runnable
接口或 Callable
接口 实现类都可以被 ThreadPoolExecutor
或 ScheduledThreadPoolExecutor
执行。Executor
)
Executor
,以及继承自 Executor
接口的 ExecutorService
接口Future
)
Future
接口以及 Future
接口的实现类 FutureTask
类都可以代表异步计算的结果SQL
语句的Java API
,它由一组用Java编程语言编写的类和接口组成接口/类 | 功能说明 |
---|---|
Connection | 数据库连接, 用于执行SQL语句 |
DriverManager | 数据库驱动管理类,用于加载和卸载各种驱动程序,并建立于数据库的连接 |
Statement | 此接口用于执行SQL语句并将数据检索到ResultSet 中 |
PreparedStatement | 此接口用于执行预编译的SQL语句 |
ResultSet | 结果集接口,提供检索SQL语句返回数据的各种方法 |
CallableStatement | 此接口用于执行SQL存储过程的语句 |
经常使用外部库jar来实现JDBC连接数据库,如org.postgresql.jar
、mysql-connector-java.jar
等。
GUI
(图形用户界面)为程序提供图形界面,它最初的设计目的是为程序员构建一个通用的GUI
,使其能够在所有的平台上运行Swing
组件中大多数GUI组件都是Component
类的直接子类或间接子类,JComponent
类是Swing
组件各种特性的存放位置,这些组件的特性包括设定组件边界、GUI组件自动滚动等。Swing
组件中最重要的父类是Container
类,而Container
类有两个最重要的子类,分别为java.awt.Window
与java.awt.Frame
,除了以往的AWT类组件会继承这两个类之外,现在的Swing
组件也扩展了这两个类。JFrame
:最常用的窗体,可以用来创建带有标题栏、边框、菜单栏、状态栏的窗口。JDialog
:用来创建对话框,它可以用来创建带有标题栏、边框、按钮、文本框等的窗口。JWindow
:用来创建无边框的窗口,它可以用来创建不带有标题栏、边框、菜单栏、状态栏的窗口。getContentPane()
方法将窗体转换为容器,然后在容器中添加组件或设置布局管理器。JFrame j = new JFrame("title"); // 创建窗体 || Container c = j.getContentPane(); // 获取内容面板 || c.setLayout(new FlowLayout()); // 设置布局管理器 || c.add(new JButton("Button")); // 添加组件 || j.pack(); // 自动调整窗体大小 || j.setVisible(true); // 显示窗体(表示窗体可见)
setDefaultCloseOperation()
方法关闭窗体,有以下四个方式:
DO_NOTHING_ON_CLOSE
什么都不做就将窗体关闭EXIT_ON_CLOSE
程序退出时将窗体关闭HIDE_ON_CLOSE
示隐藏窗口的默认窗口关闭DISPOSE_ON_CLOSE
任何注册监听程序对象后会自动隐藏并释放窗体JDialog
窗体是Swing
组件中的对话框,它继承了AWT组件中的java.awt.Dialog
类。JDialog
窗体的功能是从一个窗体中弹出另一个窗体,就像是在使用IE浏览器时弹出的确定对话框一样。JDialog窗体实质上就是另一种类型的窗体。Swing
中显示文本或提示信息的方法是使用标签,它支持文本字符串和图标。JLabel
类定义,它的父类为JComponent
类。public JLabel(String text,Icon icon,int aligment):// 创建一个带文本,带图标的JLabel对象,并设置标签内容的水平对齐方式
Swing
中的图标可以放置在按钮、标签等组件上,用于描述组件的用途。图标可以用Java支持的图片文件类型进行创建,也可以使用java.awt.Graphics
类提供的功能方法来创建。paintIcon(Component c, Graphics g, int x, int y)
、getIconWidth()
、getIconHeight()
。AbstractButton
类中继承而来的(JButton
)public JButton(String text, Icon icon)
, 里面的参数可变Swing
中常用的面板包括JPanel
面板以及JScrollPane
面板。JPanel
面板可以聚集一些组件来布局。读者首先应该明确的是面板也是一种容器,因为它也继承自java.awt.Container
类。FlowLayout
Swing
中是较为常见的组件,用于触发特定动作。Swing
中提供多种按钮,包括提交按钮、复选框、单选按钮等,这些按钮都是从AbstractButton
类中继承而来。JButton
对象表示:public JButton(String text, Icon icon)
通过使用上述构造方法,在Swing
按钮上不仅能显示文本标签,还可以显示图标。
JRadioButton
)显示一个圆形图标,并且通常在该图标旁放置一些说明性文字,而在应用程序中,一般将多个单选按钮放置在按钮组中,使这些单选按钮表现出某种功能,当用户选中某个单选按钮后,按钮组中其他按钮将被自动取消。public JRadioButton(String text, boolean selected)
Swing
类中有一个ButtonGroup
类用于产生按钮组,一般就实例化一个它的对象。JCheckBox
)在Swing
组件中的使用也非常广泛,它具有一个方块图标,外加一段描述性文字。AbstractButton
类,构造方法如下:public JCheckBox(String text, boolean selected)
Swing
中提供两种列表组件,分别为下拉列表框与列表框。public JComboBox(ComboBoxModel aModel)
public JComboBox(Object[] items)
public JComboBox(Vector items)
ComboBoxModel
类型、数组或Vector
类型中。JComboBox
模型ComboBoxModel
的情况比较多。ComboBoxModel
为接口,它代表一般模型,可以自定义一个类实现该接口,然后在初始化JComboBox
对象时向上转型为ComboBoxModel
接口类型,但是必须实现以下两种方法:
public void setSelectedItem(Object item)
public Object getSelectedItem()
JPasswordField
)与文本框的定义与用法基本相同,唯一不同的是密码框将用户输入的字符串以某种符号进行加密javax.swing.JPasswordField
类来创建的public JPasswordField(Document docModel,String text,int fieldWidth)
actionListener
)和焦点监听器(focusListener
)JavaFX
是Java
平台的GUI
开发框架,它提供了丰富的组件,可以用来开发出具有GUI
界面的Java
应用程序。HTML
是一种结构CSS
是视觉效果JavaScript
是行为UI
的程序构造之外,还可以使用声明性 XML
标记。事实证明,XML
的层次结构非常适合描述用户界面中组件的层次结构。JavaFX
的 XML
格式称为 FXML
Controller
) 链接``` FXMLLoader loader = new FXMLLoader(); URL xmlUrl = getClass().getResource(“/mainScene.fxml”); loader.setLocation(xmlUrl); Parent root = loader.load();
primaryStage.setScene(new Scene(root)); primaryStage.show(); ```
.fxml
<?xml version="1.0" encoding="UTF-8"?>
import
<?import java.lang.*?><?import java.util.*?><?import javafx.scene.*?><?import javafx.scene.control.*?><?import javafx.scene.layout.*?>
Maven
:Apache Maven是一个开源的项目管理工具,它使用XML格式的项目对象模型(POM)文件来描述项目的构建、报告和文档信息。Gradle
:Gradle是一个基于Groovy的项目自动化构建工具,它使用一种基于Groovy的特定领域语言来声明项目配置,通过插件来实现自动化构建。