文章目录
第二章 Java语言开发环境
-
环境变量配置:PATH、CLASSPATH(类路径)
-
main 方法是一个特殊的方法, 每个 java 应用程序都需要含有这个方法, 因为它是程序执行的入口, 由它再去调用其他方法
-
main 方法必须放在类中, 而且格式固定:
public static void main(String[] args) 或 public static void main(String args[])
-
Java 区分大小写
-
同一个 .java 文件中可以定义多个类, 但是只能定义一个公共类, 且文件名必须和公共类相同
-
只能有一个公共类,但不是必须有公共类
-
main()不一定放在公共类中,但是命令行运行的是main()所在的类。
第三章 Java语言基础
考点:
- 8个基本数据类型以及各类型所占的字节数
- 基本类型间的相互转换
- 表达式中的类型自动转换
- Java中的标识符命名规则
- 表达式中的运算符及其优先级(重点看下短路与、短路或)
- 选择语句、循环语句、跳转语句
- 一维数组、二维数组的定义及初始化
- 数组作为参数传递时的形参与实参关系
1、标识符定义规则:
- 由(Unicode)字母、数字、下划线、$ 组成,不能由数字开头.
- 不能是Java中的保留字(关键字)
- 大小写敏感,长度无限制
2、注释
-
//
单行注释: 表示从此向后,直到行尾都是注释 -
/*……*/
块注释: 在“/”和“/”之间都是注释 -
/**……*/
文档注释: 所有在/**
和*/
之间的内容可以用来自动形成文档——javadoc
3、 变量
两种变量:局部变量、类成员变量,均需要先定义后使用。
局部变量需要赋值才能使用,类成员变量不需要。因为局部变量没有默认值,而类成员变量会默认初始化。
变量名区分大小写,使用驼峰命名法。
4、常量
(1)数值常量
(2)符号常量:使用修饰符final
定义符号常量,常量的值一旦确定不可更改。
final int a=10;
System.out.println(a);
final int a;
a=10;
System.out.println(a);
类静态成员常量只能在定义时初始化;方法中的常量(局部常量)可以在定义时初始化,也可以先定义,以后再初始化。
5、基本数据类型
(1)整型(int、short、long、byte)
十进制:42
,八进制:052
,十六进制:0x2A、0X2a
整型常量默认以int
类存储,后面加上L
或l
,则以long
类型存储
(2)实型(float、double)
实型常量默认以double
类型存储,后面加上F
或f
则以float
类型存储。
十进制:-3.5f 、0.0f 、123.45f 、+678.9f
,采用十进制表示法时,小数点的两侧都必须有数字, 缺一不可。
科学表示法: <尾数> E <阶码 >
,-1.234567E+12
- 尾数必须有,但小数部分可无
- 阶码必须有,必须是整数
- 基数是10
(3)布尔型(boolean)
布尔型只有true
和false
,Java中不可将布尔类型看做整型值。
(4)字符型(char)
表示单个字符,采用16位二进制 Unicode 编码表示(2字节),
字符常量是用两个单引号括起来的一个字符,也可用unicode编码表示一个字符常量,如\u0041
字符型变量的类型是char
, 2个字节
7、运算符及表达式
(1)自增、自减
a=5
++a + 10 = 16, a = 6
a++ + 10 = 15, a = 6
--a + 10 = 14, a = 4
a-- + 10 = 15, a = 4
(2)如果整数相除,则结果取整;如果浮点数相除,则是通常意义上的除法,如5.0/2.0结果为2.5
注意:
例题:
即向上取整
(3)关系运算符(== ,!= ,< ,<= , > ,>= , instanceof
)
instanceof: 用来确定一对象是否是某一指定类的对象
class Demo {
public static void main(String args[]) {
Demo t = new Demo();
if (t instanceof Demo)
System.out.println("是");
}
}
(4)逻辑运算符
(5)移位运算符
int a=7,c; //a= 00000000000000000000000000000111
c = a>>3; //c=00000000000000000000000000000000=0
c = a << 3; //c=00000000000000000000000000111000=56
c = a >>> 3;//c=00000000000000000000000000000000=0
int a=-8;
System.out.println(a>>>1); //结果2147483644
int i=88>>32;
System.out.println(i); //结果88
在进行移位之前,java系统首先把移的位数与被移位的位数求余数,然后移动这个位数
问:如何用一个表达式计算2的X次方?
答:1 << x
问:如何获取一个整数的第4个比特(从低位算起)?
答:(x & (1<<3))>> 3
(6)赋值运算符
- boolean型的只能赋给boolean型
- 其他七种类型如果能自动转换则可直接赋值,否则要进行强制类型转换
8、运算符优先级
(1)优先级
- ( )>单目运算符>双目运算符>三目运算符>赋值运算符
- 双目:算术>移位>关系>逻辑。
(2)结合性
- 大多数运算符结合性为从左至右
- 赋值运算符的结合性为从右至左
例子:a=8 – 2 * 3 <4 && 5 < 2
,结果为false
9、数据类型转换
(1)自动类型转换
- Java中整型、实型、字符型数据可以混合运算。
- 运算过程中,Java自动把精度较低的类型转换为另一种精度较高的类型。
- 低精度的值赋给高精度的变量可以自动转换,不出现编译错误;相反会出现编译错误,需要强制转换
- 如果byte、short、char在一起运算时,会先将这些值转换为int型。再进行运算,结果为int型。
(2)手动强制类型转换
b=(byte)345; //b为345%256=89
i=(int)(3.8+6); //强制转换后小数部分被截去,i得到9
运算时注意(一般的运算都有类型提升功能):
- 在运算过程中,运算的结果至少是int型,即如果参与运算的两个数级别比int型低或是int型,则结果为int型
- 参与运算的数据如果有一个级别比int型高,则运算结果的类型与类型级别高的数相同
- 参与运算的两个数据如果类型不一样,会先把低级的数据转换成高级的类型的数据后再作运算,结果是高级的类型
(3)隐含强制类型转换
- Java中允许把int类型的常量赋给byte、short变量时不需要强制类型转换
- 但是把int类型的变量赋给byte、short类型的变量时必须强制转换,否则会出错
byte b=123;//合法
short s=123;//合法
b=b+3; //不合法
int i=123;
byte b=i; //不合法,正确的做法是byte b=(byte)i;
byte a = 1;
byte c = (byte)(a + b); //合法
(4)练习:
'A'+2+2.5
为double类型
int x=1; float y=3.5f;
,则 x+(int)y*2
值为7,为int类型
char a='a'
,则 a + 1
为98,int类型
(5)若运算符两边有字符串类型(双引号),则+
为字符串连接符。
"a" +1 结果为"a1"
"a"+1+1 结果为"a11"
"a"+(1+1) 结果为"a2"
10、标准输入输出(I/O)
System.in是字节流,作用是从标准输入读一个字节。
read() 方法返回值是 int 类型!
- int read() 从流中读取一个字节并将该字节作为整数返回,若没有数据则返回-1
- int read(byte b[]) 从流中读取多个字节放到b中, 返回实际读取到的字节数
- int read(byte b[],int off,int len) 从流中读取最多len字节的数据, 放到数组b的下标off开始的单元中,返回读取到的字节数
注意:调用 read() 函数一定要 try catch,且为IOException
try{
char ch=(char)System.in.read();
System.out.println(ch);
}catch(IOException e){}
}
从键盘读一数字串或一个整数:
import java.io.*;
class ReadStringOrInt{
public static void main(String args[]){
byte buf[]=new byte[20];
String str;
int anInt;
try{
System.in.read(buf);
str=new String(buf);
anInt=Integer.parseInt(str.trim());
}catch(Exception e){ }
}
}
11、switch语句
使用switch-case必须注意:
- 表达式必须是符合byte,char,short和int类型的表达式, 不能是浮点类型或字符串,case子句中常量的类型必须与表达式的类型相容,且每个常量必须不同
- case后面可以有多条语句,不用加{}
- default子句是可选的。如果有default,当表达式的值与case子句的值都不匹配时就会执行default分支,如果既没匹配也没default,那就什么也不执行
- break为跳转语句,表示跳出switch结构,即终止switch语句的执行。如果没有break语句,则switch在执行完一个case分支后,流程控制转移到下一个case继续执行,不再匹配,直到遇到break为止。
- 多个case子句可以共享相同的语句块
12、数组
Java中,数组是独立的类,有自身的方法,不只是变量的集合。
数组作为函数参数传入,形参的值变化,实参也会变化。
public class test {
public static void main(String[] args) {
int[] a = new int[] { 1, 2, 3 };
System.out.println("Outside1: " + a[0]);
test(a);
System.out.println("Outside2: " + a[0]);
}
static void test(int[] a) {
a[0] = 0;
System.out.println("Inside: " + a[0]);
}
}
上述程序输出:
Outside1: 1
Inside: 0
Outside2: 0
(1)一维数组
一维数组的声明:
int list[ ];
int[] list;
一维数组的初始化:
int[] a={1,2,3,4}
int[] a=new int[4];
a[0]=1;a[1]=2;a[2]=3;a[3]=4
int[] a=new int[]{1,2,3,4};
int[] a;
a=new int[]{1,2,3,4};
Java 在对数组元素操作时会对数组下标进行越界检查,以保证安全性。
int[] arr = {1,2,3,4};
System.out.println(arr[4]);
会抛出异常:java.lang.ArrayIndexOutOfBoundsException
数组可调用成员变量 length
查看其长度。
int[] arr = {1,2,3,4};
System.out.println(arr.length); //输出4
(2)二维数组
二维数组为一个特殊的一维数组,其每个元素又是一个一维数组。
二维数组的声明:
int intArray[ ][ ];
int[ ][ ] intArray;
二维数组的创建:
二维数组的初始化:
(3)数组相关函数(java.util.Arrays)
Arrays.sort()
对数组x内的元素进行排序(升序)Arrays.binarySearch(x,1)
二分查找,在数组x中查找1,输出0;如果没找到,则会输出一个<0的数Ayyars.fill()
填充数组System.arraycopy()
拷贝数组
第四章 Java面向对象
考点:全是重点
1、理论基础
(1)封装
(2)继承
(3)多态:指程序中相同名字表示不同含义的情况。
- 单个类:一个类可以有多个具有相同名字的方法,在使用时由传递给它们的不同个数和类型的参数来决定使用哪个方法(重载)
- 多个类:子类对父类方法的覆盖,即子类和父类可以有多个相同名字的方法,运行的事件决定到底执行哪个特点的版本(覆盖)
(4)类首说明
[修饰符] class 类名 [extends父类名] [implements接口名列表]
- 类的修饰符:public、abstract、final
- 访问权限修饰符:public 或缺省
- abstract 抽象类(不能创建对象,可能包含未实现的方法)
- final 最终类(不能被继承,即不能有子类)
- extends (单)继承
- implements 实现(接口)
2、成员变量
定义在成员函数中的变量只是局部变量,不是成员变量。类的成员变量和类中的局部变量可以重名。
(1)访问权限修饰符
- public:怎样都可以访问
- protected:只有在不同包的非子类访问不到
- 缺省:在同一个包中可以访问(包变量)
- private:只有同一个类可以访问
大小:public >protected >缺省>private
注意: 在main方法中,不管是本类还是非本类,要访问实例变量都要创建对象,可以引申到其他所有的类方法(静态方法) 中
(2)静态变量(static)
静态变量也叫类变量,可以用类访问,也可以用该类的对象访问。
形式:类名.静态成员变量
或 对象名.静态成员变量
(3)对象常量
- final定义的成员变量叫最终变量——java中的常量
- 常量在说明以后就不能改变其值
- 无论是实例变量,还是类变量,都可以被说明成常量。
- final修饰符和static修饰符并不冲突 (类常量)
类常量一定要在定义时就给定初始值;对象常量可以先定义,然后在每一个构造函数中进行赋值
static final int x = 5;
//static final int x; x = 5; //Wrong!
4、成员方法
(1)方法的修饰符
- 访问修饰符:缺省、public、protected、private
- 非访问修饰符:static(类方法/静态方法)、abstract(抽象方法:无方法体)、final(最终方法:不能由子类改变)、synchronized(同步方法)、native(本地方法)
(2)方法体
方法体也可以是一个分号“;”,表示无具体方法(方法还没有实现,即只是一个方法框架。当且仅当方法的修饰符中有abstract
或native
时,方法才可无方法体。
abstract void play();
(3)类方法
类方法是对整个类而言的,而不是针对类的对象,方法体中不能有与对象有关的内容。
- 在类方法中不能直接引用对象变量。
- 在类方法中不能使用super、this关键字
- 类方法不能直接调用类中的对象方法。
(4)方法的重载
-
含义:类中定义多个带有不同参数的同名方法,是实现多态性的方法之一。
-
规则:多个方法有相同的名字,但是这些方法的参数列表必须不同(包括参数个数不同、参数类型不同、参数类型的顺序不同)
-
仅返回值类型不同不能实现重载
-
除了同一个类,方法的重载也可以在父类和子类之间
5、构造方法与对象的创建
(1)构造方法
- 构造方法的方法名与类名相同。
- 构造方法没有返回类型,也不能写 void。
- 构造方法的主要作用是完成对类对象的初始化工作。
- 每个类都至少有一个构造方法,如果没有显示地定义构造方法,Java会自动提供一个缺省的构造方法。但是只要类中显式定义了一个或多个构造方法,而且所有显式定义的构造方法都带参数,那么将失去缺省构造方法。
- 通常会按照需要定义多个构造方法,即构造方法的重载
(2)this的使用
this的含义:
- 在方法中,关键词this用来本类对象。
- 在普通非静态方法中,this表示调用这个方法的对象;
- 在构造方法中,this表示新创建的对象
在所有的非static方法中,都隐含了一个参数this。而static方法中,不能使用this。
6、继承
Object 类是 Java 中所有类的直接或间接父类。
(1)属性与方法
-
子类可以继承父类所有非 private 属性及方法(构造函数不被继承)
-
属性的隐藏:子类可以定义与父类相同名字的属性,称为属性的隐藏
-
方法的覆盖:子类可以定义与父类中的方法具有相同首部的方法(包括方法名、参数列表、返回类型和异常抛出),称为方法的覆盖。
-
方法的重载:方法名相同,但参数列表不同。实际是相当于在子类中新加了一个方法。
-
被覆盖和重载的方法均不能为private。
-
某类的静态成员为该类及该类的所有子类所共有
-
如果子类中新定义的静态成员变量与父类中的某个静态成员变量同名,则这两个静态成员变量相互独立(可以使用类名进行调用)
-
不允许在子类中降低成员(包括变量和方法)的访问权限
(2)super的使用
super代表父类对象,在继承中有重要的作用
两种使用情况:
① 子类隐藏了超类中的变量或方法,而在程序中又要使用超类中被隐藏的变量或方法时
格式:super.变量 ; super.方法([参数表])
class Country
{
String name;
void value(){ name="China"; }
}
public class City extends Country
{
String name;
void value()
{
name="Hefei";
//调用同名的方法
super.value();
System.out.println(name);
System.out.println(this.name);//调用同名的成员变量
System.out.println(super.name);
}
public static void main(String args[])
{
City c=new City();
c.value();
}
}
运行输出:
Hefei
Hefei
China
② 在子类的构造方法中引用超类的构造方法时
格式: super([参数表])
在构造方法中使用super时,super语句必须放在第一句
建议:在子类的构造方法中最好能明确使用super调用父类的构造方法给从父类继承来的变量初始化
不明确的使用super构造父类构造方法可能会出错(当父类中没有不含参的构造函数时)
(3)构造方法的调用顺序(重要)
构造方法调用顺序:
- 构造方法是不能继承的,因为继承意味着与父类的构造方法同名,但显然子类的构造方法不可能与父类的构造方法同名。
- 但是创建一个子类对象时,子类的构造方法一定会调用父类(直接和间接)的构造方法,以此类推,将继承阶层串联起来,使每个父类的构造方法皆被调用。
一个复杂对象的构造方法调用顺序如下:
① 首先调用父类的构造方法(递归,也就是说,最顶级的父类会最先调用)。② 然后根据各成员的声明顺序,执行成员变量的初始化语句。
③ 最后执行自己构造方法中的各语句。
例题:
(4)父类对象与子类对象的转换
类的实例对象之间可以相互进行类型转换,分为:
- 隐式自动类型转换
- 显示强迫类型转换:(类名)类对象
即: - 子类对象可以显式或隐式的转为父类对象,直接向父类对象赋值即可。
- 而只有当父类对象实际指向的是一个子类对象时,才能将其转换为子类对象,且还需要使用强制类型转换。
例子:
class A
{String s = "A"}
class B extends A
{String s = "B";}
public class test{
public static void main(String[] args){
A a1 = new A();
B b1 = new B();
A a3 = b1; //合法,子类对象转父类对象
A a2 = new B();
B b3 = (B)a2; //合法,强制类型转换
//B b4 = (B)a1 //不合法,父类对象指向的不是子类对象
}
}
(5)抽象类与抽象方法
(6)final类和final方法
final类:类被 final 修饰,说明它是最终类,不能被继承。
final方法:方法被 final 修饰,说明它是最终方法,不能被覆盖(重写)。
注意:所有包含在 final 类中的方法,都被默认为是 final 的。因为这些方法不可能被子类所继承,所以不可能被重载,自然都是最终的方法。
7、接口(interface)
(1)接口的一些概念
接口作用
- 实现程序设计和实现分离。
- 弥补Java只支持单重继承的不足
- 约束实现接口的类
接口的权限修饰符有两种:
- 缺省,则只能同包访问
- public ,则任意访问
接口可以多继承(使用extends继承其他接口),接口中的方法都是抽象的。
接口的说明:
[修饰符] interface 接口名[extends] [接口列表]
{
接口体
}
(2)接口体
- 接口中的成员变量:都是隐含public、static、final的——静态最终变量(常量)
- 接口中说明的方法都是抽象方法,所有方法隐含public和abstract的
- 接口中的方法不能使用static/native/synchronized/final修饰符
例如,在接口体中int STEP=5;
等同于public static final int STEP=5;
(3)接口的使用(implements)
[类修饰符] class类名 [extends子句] [ implements 子句]
在implements子句中可以包含多个接口类型,各个接口类型之间用逗号隔开
利用接口实现多重继承:
8、多态
(1)继承(覆盖)
…
(2)向上转型
(3)动态绑定
9、包
本身是一种命名机制(防止同名的类发生冲突),具体的表现就是一个文件夹
package 包名;
import package1[.package2…].(classname|*);
10、Java变量及其传递
(1)基本数据变量与引用型变量
- 基本型变量(8种基本数据类型) :在栈中直接存值。
- 引用型变量(对象、接口、数组):实体值存在堆中,栈中存储堆首地址。
例子:
(2)成员变量与局部变量
- 从变量在内存中的存储方式看,成员变量是对象的一部分,而对象是存在于堆中的,而局部变量是存在于栈中的。
- 成员变量如果没有赋初值,则会自动以该类型的默认值(0,false,null等)赋值;而局部变量则不会自动赋值,必须显示地赋值后才能使用。
(3)变量的传递
(5)引用型变量的比较
-
比较两个变量是否是同个变量(引用值相等):== 和 !=。
-
比较两个变量的内容是否相等,用 equals() 方法。
自己定义的类要实现比较内容,则必须重写 equals() 方法:
public boolean equals(Object obj) {
if(obj == null) return false;
if(this == obj) return true;
if(getClass() != obj.getClass()) return false;
Person p = (Person)obj;
if(name.equals(p.name) && age == p.age) return true;
return false;
}
11、内部类
考点:会些图形用户编程中的事件处理
(1)内部类的定义与使用
- 定义:将类的定义置入一个用于封装它的类(外部类)里(内部类与外部类不能同名)
- 作用:逻辑分组,隐藏细节
- 创建非静态内部类的对象时一定要确保已经有一个外部类对象
- final 表明内部类不能被继承;abstract 表明内部类不能被实例化;static 表明是一个静态内部类。
- 内部类中可以直接访问外部类的其他属性与方法的,即使它们是private的
- 若内部类中有和外部类同名的属性或方法,可以使用 outerClass.this 表示外部类的引用。
(2)方法和作用域中的内部类
(3)匿名内部类
-
定义:类或方法中定义的一种没有类名的特殊内部类。
-
作用:当需要创建一个类的对象而且用不上它的名字时,使用内部类可以使代码看上去简洁清楚。
-
类中不能定义构造方法,因为它没有名字。
第五章 异常处理
考点:
- 运行时异常与非运行时异常的区别
- try…catch…finally的使用
- 会使用throw自定义抛出异常,throws声明抛出异常
1、程序的错误分为:
- 编译错误
- 运行错误
2、异常的分类
(1) 运行时异常
RuntimeExceptiontion类及其所有子类。运行时异常时程序员编写程序不正确所导致的异常。理论上,程序员可以通过检查和测试查出制类错误。
如除数为零等,错误的强制类型转换、数组越界访问、空引用。
(2)非运行时异常(一般异常)
指可以由编译器在编译时检测到的、可能会发生在方法执行过程中的异常,如找不到指定的文件等,这不是程序本身的错误,如果这些异常情况没有发生,程序本身仍然是完好的。
注意:编译器强制要求Java程序必须捕获或声明抛出所有非运行时异常,但对运行时异常不作要求。
3、try-catch-finally异常处理
可以用try-catch-finally语句进行捕获和处理
(1)try语句
- 将可能抛出一个或若干个异常的代码放入try语句块中
- 应当尽量减小try代码块的大小,不要将整个程序代码全部放入try语句块中,而是应当仔细分析代码,在可能出现异常情况的地方用try进行监控
(2)catch语句
- try语句后面必须跟有一个或多个catch语句来处理try中产生的异常事件。如果try语句中未产生异常,那么catch语句将不执行。
- catch语句需要一个参数:一个异常类名和该类的参数。(该异常类必须是Throwable类的子类)
- finally总是执行,catch块不一定执行
(3)finally语句
- 无论try块中是否产生异常,也不管产生的异常是否会被捕获,finally中的语句最终都会被执行
- 为异常处理事件提供一个清理机制
(4)格式
try{
//调用可能产生异常的方法及其它java语句
}
catch(异常类名1 异常对象名e){
//异常处理语句块
}
catch(异常类名2 异常对象名e){
//异常处理语句块
}
finally{
//最终处理
}
4、throws抛出异常
声明抛出异常:不捕获异常,而是将异常交由上一层处理,在其他地方捕获异常
- 应该向编译器表明:此方法可能会抛出异常,但方法本身不会捕获它
- 可以在方法头中用throws子句来实现此功能
带throws异常说明的方法说明形式如下:
... 方法名(...)[throws 异常类列表]
{方法体}
例:
class Test {
public String getInput() throws IOException {
System.in.read();
return null;
}
}
注意:
- 方法抛出的异常类时throws子句中指定的异常类或其子类
- 不是所有可能发生的异常都要在方法的说明中指定,从Error类中派生出的异常和从RuntimeException类中派生的异常就不用在方法声明中指定
5、throw抛出异常
(1)在捕获一个异常前,必须有一段Java代码来生成和抛出一个异常对象。
Java也可以用throw语句抛出异常,格式如下:
throw ThrowableObject;
(2)使用throw语句应注意:
- 一般这种抛出异常的语句应该在满足一定条件执行,例如把throw语句放到if分支中
- 含有throw语句的方法,应该在方法头定义中用throws语句声明所有可能抛出的异常
(3)抛出异常三步骤:
①确定异常类
②创建异常类的实例
③抛出异常
6、例子
import java.io.IOException;
public class ThrowTest {
static String getInput() throws IOException { //throws声明抛出异常
char[] buffer = new char[20];
int counter = 0;
boolean flag = true;
while (flag) {
buffer[counter] = (char) System.in.read();
if (buffer[counter] == '\n')
flag = false;
counter++;
if (counter >= 20) {
//throw抛出异常
throw new IOException("buffer is full");
}
}
return new String(buffer);
}
public static void main(String[] args) {
//try-catch语句捕获异常
try {
System.out.println(getInput());
} catch (IOException e) {
e.printStackTrace();
}
}
}
习题: 当下面的程序的输入是“1 2 3 4”时,程序的输出是什么,如果把红色的语句去掉,输出是什么?
public class J_Test {
public static void main(String args[]) {
try {
mb_method1(args); //1
} catch (Exception e) { //在method1里捕获了异常,这里不再捕获
System.out.print('m');
}
System.out.print('n'); //7.输出 n
}
static void mb_method1(String a[]) {
try {
mb_method2(a); //2
System.out.print('a');
} catch (Exception e) {
System.out.print('b'); //4.输出 b
} finally {
System.out.print('c'); //5.输出c
}
System.out.print("d"); //6.输出 d
}
static void mb_method2(String a[]) {
System.out.println(a[a.length]); //3.数组越界异常
}
}
上述程序输出:bcdn
若去掉mb_method1中的catch语句:
public class J_Test {
public static void main(String args[]) {
try {
mb_method1(args); //1
} catch (Exception e) { //method1中有未捕获的异常,此处捕获
System.out.print('m'); //5.输出m
}
System.out.print('n'); //6.输出n
}
static void mb_method1(String a[]) {
try {
mb_method2(a); //2
System.out.print('a');
} finally {
System.out.print('c'); //4.输出c,但未捕获异常
}
System.out.print("d");
}
static void mb_method2(String a[]) {
System.out.println(a[a.length]); //3.数组越界异常
}
}
输出:cmn
第六章 Java的基本类库
1、Java.lang包
考点:
- Java.lang.Object:Java整个类层次结构的根节点
- Java.lang.System:提供对操作系统的访问,包括默认的I/O流环境遍历、自动垃圾收集、系统时间和系统属性
- Java.lang.String:不可改变的静态字符串
- Java.lang.StringBuffer:动态可变的字符串
- Java.lang.math:提供数学常用的各种函数
Java.lang.String
(1)String类的所有方法都不会改变String类对象内容,要改变String类对象的值就必须创建一个新的String对象
String a = "hello";
System.out.println(a);
String a="hello";
String b=new String("java"); //实际上创建了两个对象
(2)String是类,在比较字符串内容时,不能用==
,而应该用equals
方法。String类覆盖了Object类的equals方法
(3)Java为节省内存空间、提高运行效率,编译时将String Pool中所有相同的字符串合并,只占用一个空间。导致引用变量a和b指向同一个对象,用==比较a和b,一定是相等的
String a="hello";
String b="hello";
if(a==b) {
System.out.println("相等");
}else{
System.out.println("不等"); }
//输出结果:相等
由于java是在编译时将StringPool中所有相同的字符串合并,所以如下程序,并未将a指向的字符串与c指向的字符串合并,导致a和c指向的不是同一个对象。
String a="hellojava";
String b="java";
String c="hello"+b;
if(a==c){
System.out.println("相等");
}else{
System.out.println("不等");
}
//输出结果:不等
(4)String对象作为参数传递和基本数据类型效果一样,因为它是不可改变的字符串,即形参变化不会引起实参的变化。
(5)常用字符串方法
求子串(字符串可看做一串字符,第一个字符下标为0):
String a="hello";
String b=a.substring(0,4);//得到“hell”
String c=a.substring(2,3);//得到“l”
求字符串中字符的个数(length函数):
String a="hello";
int b=a.length();//得到5
得到字符串中的某个字符(charAt函数):
String a ="hello";
char b =a.charAt(0);//得到下标为0的字符h
字符数组转换为String:
char[] a = {'a','b','c','d'};
String b = new String(a);
String转换为字符数组:
String a = "hello";
char[] b = a.toCharArray();
字节数组转换为String:
byte [] a={65,66,67,68};
String b=new String(a);//得到ABCD
大小写转换:
String s1="Hello";
String s2=s1.toUpperCase();//得到“HELLO”
String s3=s1.toLowerCase();//得到“hello”
java.lang.StringBuffer
线程安全的可变字符序列
(1)三种构造方法:
//构造一个其中不带字符的字符串缓冲区,其初始容量为 16 个字符
StringBuffer sb = new StringBuffer();
//构造一个不带字符,但具有指定初始容量的字符串缓冲区
StringBuffer sb = new StringBuffer(int capacity);
//构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容
StringBuffer sb = new StringBuffer(String str);
(2)更新方法
StringBuffer s = new StringBuffer("hello");
//添加
s.append("java"); //hellojava
//插入
s.insert(5, "sun"); //hellosunjava
//修改
s.setCharAt(0, 'H'); //Hellosunjava
//删除
s.delete(5, 8); //Hellojava
(3)String 对象和 StringBuffer 对象相互转换:
//String转StringBuffer
StringBuffer sb = new StringBuffer("hello");
//StringBuffer转String
String s =sb.toString();
(4)与String类不同,StringBuffer类的对象作为参数传入时,形参的改变会引起实参的改变。如下例:
(5)利用StringBuffer类将键盘输入的数据建立一个字符串实例
import java.io.IOException;
public class StringBufferToString {
public static void main(String[] args) {
char ch;
try {
int length = 20;
StringBuffer strb = new StringBuffer(length);
while ((ch = (char) System.in.read()) != '\n') {
strb.append(ch);
}
String str = strb.toString();
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
}
数据类型类
//将字符串转换为int型
String s = "1234";
int i = Integer.parseInt(s);
//将int型转换为字符串
int i=1234;
String s=Integer.toString(i);
float f=Float.parseFloat(s); //转成单精度数
double d=Double.parseDouble(s);
其他Double, Float等数据类型类以此类推
Math类(java.lang.Math)
//得到一个[0,1)之间的随机数
double c = Math.random();
//获取20~80之间的随机数
(int)(Math.random()*60+20)
或
(int)(Math.random()*60)+20
//返回x的y次方
double a = Math.pow(2, 4);
//返回x的平方根
double a = Math.sqrt(4);
2、向量类java.util.vector
(1)Vector<E>
- 可以实现可增长的对象数组
- Vector是同步的
- 向量通过维护caopacity和capacityIncrement来优化存储管理
(2)向量Vector与数组Arrays的异同
相同点:
- 都是类,均可保存列表
不同点:
- 数组Arrays一旦定义,其空间长度不可变;而向量Vector的空间能在运行时动态的扩充或缩减
- 数组中可以存放基本数据类型,也能存放对象;向量中只能存放对象,若要存储基本数据类型,要通过基本数据类(如Integer)进行封装
(3)构造函数
//使用指定的初始容量和容量增量构造一个空的向量
Vector(int capacity, int capacityIncrement);
Vector(int capacity);
Vector();
(4)创建向量
Vector<元素类型> 向量名称 = new Vector<元素类型>(容量);
//这里元素类型不能是基本数据类型
Vector<String> v = new Vector<String>(5);
(5)重要方法:
v.add(x); //添加元素
v.elementAt(idx); //获取下标为idx的元素
System.out.println(v.size()); //元素个数
System.out.println(v.capacity()); //向量容量
v.insertElementAt(obj, idx); //在下标为idx的位置插入obj
v.setElement(obj, idx); //修改元素
v.removeElementAt(idx); //删除元素
v.clear(); //清空向量
v.contains(obj); //判断是否包含元素obj
v.indexOf(obj); //返回向量中obj的下标,若无,返回-1
(6)Vector的初始大小为10,在自动扩充时,如果没有指定每次增长的大小,则默认是翻倍增长
如下:
3、java.io包
考点:
- FileInputStream、FileOutputStream
- 字节流如何转化为字符流
- 了解File对象
- PrintStream
I/O操作注意要用try…catch…捕获异常
- 字节流
- FileInputStream
- FileOutputStream
- 字符流
- FileReader
- FileWriter
- 字节流转字符流
- InputStreamReader
- OutputStreamWriter
- 过滤流(缓冲作用)
- BufferedInputStream (针对字节流)
- BufferedReader (针对字符流)
字节流: 以字节作为基本单位进行读写
字符流: 对以字符作为基本单位的数据源或者数据目的进行读写
标准输入输出流都是字节流(System.in、System.out), 可以通过InputStreamReader
和OutputStreamWriter
转换为字符流:
InputStreamReader isr = new InputStreamReader(System.in);
char c = (char)isr.read();
System.out.println(c);
File类(java.io.File)
File f1 = new File("G:\\java-example\\myfilel.txt");
File f2 = new File ("G:\\java", "myfile2.txt");
File f3 = new File ("myfile3.txt");
字节流
FileInputStream
和FileOutputStream
的数据源都是文件,用于进行文件输入输出的处理。
(1)FileInputStream
FileInputStream:封装了从文件中读取字节的功能,该类是用来读取字节文件的,如图像文件,如果读取字符或者文本文件,则最好使用FileReader类。
FileInputStream fis = new FileInputSteam("a.jpg");
File file = new File("b.jpg");
FileInputStream fs = new FileInputStream(file);
- read()方法:读从此输入流中读取一个数据字节,当执行到文件内容末尾时返回-1
- read(byte[] b)方法:从此输入流中将最多b.length个字节的数据读入一个字节数组
返回值:每次读入的字节个数,当到达文件末尾而没有字节读入时,返回-1。
(2)FileOutputStream
构造方法:
FileOutputStream(File file)
FileOutputStream(File file, boolean append)
FileOutputStream(FileDescriptor fdObj)
FileOutputStream(String name)
FileOutputStream(String name, boolean append)
写入字节的方法:
void write(byte[] b)
void write(byte[] b, int off, int len)
void write(int b)
过滤流(BufferedInputStream、BufferedReader)
- BufferedInputStream(字节流)
- BufferedReader(字符流)
例子:
//BufferedInputStream
FileInputStream fis=new FileInputStream("text");
BufferedInputStream bis=new BufferedInputStream(fis);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("text"));
//BufferedReader
new BufferedReader(new InputStreamReader(new FileInputStream("demo.txt"),"gbk"));
字符流
(1)FileReader和FileWriter
用于字符文件的输入输出处理,是专门读取和输出字符(文本)文件的类。
//FileReader
File f=new File("d:\\t1.txt");
FileReader f1=new FileReader(f);
FileReader f2=new FileReader("d:\\t1.txt");
//方法
read( )
read(char b[ ])
read(char b[ ],int off,int len)
close()
//FileWriter
File f=new File("d:\\t1.txt");
FileWriter f1=new FileWriter(f);
FileWriter f2=new FileWriter("d:\\t1.txt");
//方法
write(char c)
write(char b[ ])
write(char b[], int off, int len)
close()
//完后一定要关闭输出流,数据才真正地写到了文件中!
字节流转字符流(InputStreamReader、OutputStreamReader)
将字节流转字符流从文件中读取数据:
import java.io.*;
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("demo.txt"), "gbk"));
String s;
//readline()到达流末尾,就返回null
while ((s = br.readLine()) != null) {
System.out.println(s);
}
//char[] buff = new char[1024];
//int len = 0;
//while ((len = br.read(buff)) != -1) {
//System.out.println(new String(buff, 0, len));
//}
br.close();
}
}
所以字节流转字符流即一层层封装:
new FileInputStream("demo.txt"); => 字节流
new InputStreamReader(new FileInputStream("demo.txt"), "gbk"); => 封装为字符流
new BufferedReader(new InputStreamReader(new FileInputStream("demo.txt"),"gbk")); => 用BufferedReader封装
BufferedReader对象有readline()方法读取一行
第七章 图形用户界面
考点:
-
创建简单窗体程序
-
面板和窗体默认布局管理器
-
如何设置窗体和组件位置、大小、背景色、前景色(函数使用)
-
掌握两种布局管理器 FlowLayout BoardLayout
-
组件:按钮、文本框、标签
-
事件处理
- 按钮动作事件
- 鼠标事件处理
- 窗体事件
-
画图(继承),记住方法
1、JFrame
通常是GUI应用程序的顶级容器组件,默认布局方式为BorderLayout
构造方法:
JFrame()
JFrame(String title)
常用方法:
setVisible(boolean b) //设置窗体是否可见(一定要写)
setSize(int width, int heidht) //设置窗体大小
setLocation(int x, int y) //设置窗体位置,(x,y)为左上角的坐标,横轴x,数轴y
setBounds(int x,int y,int width, int heidht) //同时设置位置和大小
setLayout(LayoutManager manage) //设置布局方式,如setLayout(new FlowLayout())
add(Component ob) //把其他组件ob加到窗体中
2、JDialog
第九章 多线程
1、Java实现多线程两个方式:
- java.lang.Thread(类)
- java.lang.Runnable(接口)
(1)声明一个Thread类的子类,并覆盖run()方法
import java.util.*;
public class TimePrinter extends Thread {
int pauseTime;
String name;
public TimePrinter(int x, String n) {
pauseTime = x;
name = n;
}
public void run() {
while(true) {
try {
System.out.println(name + ":" + new
Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
}catch(Exception e) {
System.out.println(e);
}
}
}
public static void main(String[] args) {
TimePrinter tp1 = new TimePrinter(1000, "Fast Guy");
tp1.start();
TimePrinter tp2 = new TimePrinter(3000, "Slow Guy");
tp2.start();
}
}
但是当类已经有了其他的直接继承父类,如JFrame,此时就可以使用下面一种方法。
(2)声明一个实现Runnable接口的类,并实现run()方法
import java.util.*;
public class TimePrinterDemo implements Runnable {
int pauseTime;
String name;
public TimePrinterDemo(int x, String n) {
pauseTime = x;
name = n;
}
public void run() {
while (true) {
try {
System.out.println(name + ":" + new Date(System.currentTimeMillis()));
Thread.sleep(pauseTime);
} catch (Exception e) {
System.out.println(e);
}
}
}
//加上主线程共3个线程
public static void main(String[] args) {
//还是需要封装在Thread中创建线程,然后使用Thread的start()方法启动线程
Thread t1 = new Thread(new TimePrinterDemo(1000, "Fast Guy"));
t1.start();
Thread t2 = new Thread(new TimePrinterDemo(3000, "Slow Guy"));
t2.start();
}
}
注意: 使用第二种方法时,在创建线程时还是用Thread类创建线程对象,把实现Runnable接口的类的对象作为Thread类的构造方法的参数,再调用Thread类对象的start()方法
(2)Thread类常用构造方法
public Thread()
public Thread(Runnable target)
(3)Thread类常用方法
- start() :启动线程,引起run()方法的调用,(创建线程 不自启动)
- sleep(Long) :将线程暂停参数指定的毫秒数,(不释放对象锁)
- Wait(Long) :将线程挂起制定的毫秒数,(释放对象锁)
- Wait( ):将线程挂起,直到当调用notify()或notifyAll()时 (这两个方法只能在Synchronized函数中或同步块中使用)
- notify() :唤起一个线程
- yield() :只希望让其他正在等待的线程有机会执行,且在没有其他线程等待时立即重新执行。
- join()方法:如果一个线程需要等待另一个线程消亡后再继续运行,则可调用希望其消亡的那个线程的join()方法。
注意:如果要用Thread.sleep()函数,一定要放在try...catch...
中
try{
Thread.sleep(1000);
}catch (Exception e){
System.out.println(e);
}
(4)线程的同步互斥
解决共享资源的访问冲突问题:只需要把一个方法声明为synchronized
,便可有效地防止冲突.
Java中每个对象都包含了一把锁(也叫“监视器”),它自动成为对象的一部分.调用任何synchronized方法时,对象就会被锁定,不可调用那个对象的其他任何synchronized方法
两种方式:
① 同步函数:
class Bank{
private int totalNum = 0;
public synchronized void add(int num) {
totalNum += num;
System.out.println("totalNum=" + totalNum);
}
}
② 同步代码块
class Bank{
private int totalNum = 0;
Object object = new Object();
public void add(int num) {
synchronized(object) {
totalNum+=num;
System.out.println("totalNum=" + totalNum);
}
}
}
第十章 网络编程
1、java.net.URL(了解)
2、java.net.URLConnction(了解)
URLConnection类对象可以与指定的URL建立动态连接,同时使用URLConnection类可以实现向服务器发送请求,将数据送回服务器
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws UnknownHostException,IOException {
// TODO Auto-generated method stub
ServerSocket serversocket=new ServerSocket(90);
Socket client=serversocket.accept();
InputStream in=client.getInputStream();
OutputStream out=client.getOutputStream();
DataInputStream dis=new DataInputStream(in);
DataOutputStream dos=new DataOutputStream(out);
String inputmsg=null;
System.out.println("Connetion Established!!");
while(true) {
inputmsg=dis.readUTF();
System.out.println("From Client: "+inputmsg);
dos.writeUTF("From Server: "+inputmsg.toUpperCase());
}
}
}
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws UnknownHostException,IOException {
// TODO Auto-generated method stub
Socket client=new Socket("localhost",90);
InputStream in=client.getInputStream();
OutputStream out=client.getOutputStream();
DataInputStream dis=new DataInputStream(in);
DataOutputStream dos=new DataOutputStream(out);
BufferedReader console=new BufferedReader(new InputStreamReader(System.in));
String inputmsg=null;
String outputmsg=null;
while(true) {
outputmsg=console.readLine();
if(outputmsg.contentEquals("break")) {
break;
}
dos.writeUTF(outputmsg);
inputmsg=dis.readUTF();
System.out.println(inputmsg);
}
}
}