概述
考点:
- Java发展历史——大概理解
- 分成J2ME,J2SE,J2EE
- Java语言的特点(开放、简单、健壮、安全、面向网络、完全的OOP、跨平台)
- Java和C++的比较:
- 辨析JVM、JRE、JDK之间的区别与联系
- Java程序(.java文件)先由编译器编译成字节码(.class),由解释器解释执行。
- 一个Java文件可以包含多个类的定义,但是只能有一个public类。文件名必须和public类同名(大小写也要一致)。
- Java的编译器:javac,解释器:java
- 两个环境变量(PATH,CLASSPATH)的作用、含义,及其配置——着重理解
- 包的定义(package)、包的导入(import)
知识点总结:
一、Java发展历史——大概理解
- Oak语言
- 1995年5月23日,Oak改名Java第一个版本
- 2000年12月相继退出J2ME,J2SE,J2EE三大平台
- 2014年3月18日Java 8正式版发布
- 2019年9月Java 13正式发布
二、J2ME,J2SE,J2EE
现在的应用领域:
- J2ME:Java的微型版
- 嵌入式系统开发,手机、PDA等无线设备(已被:IOS、Android替代)
- J2SE:Java的标准版
- Java语言基础,主要用于桌面应用软件的编程
- J2EE:Java的企业版
- 企业级的服务器端运算(JSP,Java Web编程),用于做B/S结构的应用程序,基于浏览器和服务器
三、Java语言的特点
最主要的特点:平台无关性,完全的面向对象,多线程
-
简单性
- 系统精简,对硬件环境需求不是很高
- 上手较为简单,类似C++语法
-
面向对象技术
- Java属于完全面向对象语言,实现模块化和信息隐藏
- 实现代码复用,使得可以创建很多类库
- 实现动态联编。
-
分布性
- 可以方便处理TCP/IP协议,方便访问网络上的其他对象
-
健壮性
- Java是强类型语言,编译和运行时会进行严格的检查
-
安全性
- 严格规定访问数据的权限
- 不允许网络应用程序修改本地数据
- 不能使用指针,保护私有成员的安全性
- 借助解释器来执行,阻止对内存直接访问
-
体系结构中立
- 解释器生成与体系结构无关的字节码结构的文件格式。
-
可移植性
- Java类库可移植
- 编译器用Java实现,运行器用C实现
-
解释执行
- 解释器直接对Java字节码解释执行
-
高性能
- Java的解释执行很快,字节码极快转换成机器码
- 寄存器自动分配、编译器优化字节码使得生成高质量的代码
-
多线程
- 允许在程序中并发执行多个指令流,彼此之间互相独立
- 并发是逻辑上的同时,不是物理的同时
- 由于各个线程的代码是乱序的,会带来线程调度的问题
-
平台无关性
四、Java和C++的比较
类型 | JAVA | C++ |
---|---|---|
编译 | Java源码会先经过一次编译,成为中间码,中间码再被解释器解释成机器码。对于Java而言,中间码就是字节码(.class),而解释器在JVM中内置了 | C++源码一次编译,直接在编译的过程中链接了,形成了机器码。 |
执行速度 | Java可以利用JVM跨平台。 | C++比Java执行速度快 |
面向对象特性 | Java是纯面向对象的语言,所有代码(包括函数、变量)都必须在类中定义 | C++中还有面向过程的东西,比如全局变量和全局函数。 |
指针 | Java中没有,但是有引用。 | C++中有指针 |
继承 | Java中类都是单继承的。同时Java中的接口是多继承,类对接口的实现也是多实现。 | C++支持多继承 |
运算符重载 | 不可以 | 可以 |
强制自动转型 | 不支持 | 支持 |
Goto语句 | Java不支持C、C++中的Goto语句,而是通过异常处理语句try、catch、finally等来代替C、C++中Goto来处理遇到错误时跳转的情况,使程序更可读且更结构化 | 支持 |
内存管理 | Java对此自动地进行管理并且进行垃圾回收 | C++中通过运算符new和delete来分配和释放内存 |
数据类型的支持 | 在Java中,对于这些数据类型总是分配固定长度的位数,如对int型,它总占32位,这就保证了Java的平台的无关性。 | 在C、C++中,对于不同的平台,编译器为简单数据类型,如int、float等分别分配不同长度的字节数。导致代码不可移植性 |
头文件 | Java不支持头文件,类成员的类型和访问权限都封装在一个类中,运行时系统对访问进行控制,防止对私有数据成员的操作。 | C++中用头文件声明类的原型及全局变量、库函数等 |
结构和联合 | Java中不包含结构和联合,所有的内容都封装在类中。 | C++中的结构和联合中所有成员均为公有,这就带来了安全性问题 |
预处理 | Java不支持宏,它通过关键字final来声明一个常量,以实现宏定义中广泛使用的常量定义。 | C、C++中用宏定义来实现的代码给程序的可读性和安全性带来了困难 |
五、辨析JVM、JRE、JDK之间的区别和联系
-
JVM :英文名称(Java Virtual Machine),就是我们耳熟能详的 Java 虚拟机。它只认识 xxx.class 这种类型的文件,它能够将 class 文件中的字节码指令进行识别并调用操作系统向上的 API 完成动作。所以说,jvm 是 Java 能够跨平台的核心,具体的下文会详细说明。
-
JRE :英文名称(Java Runtime Environment),我们叫它:Java 运行时环境。它主要包含两个部分,jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
-
JDK :英文名称(Java Development Kit),Java 开发工具包。jdk 是整个 Java 开发的核心,它集成了 jre 和一些好用的小工具。例如:javac.exe,java.exe,jar.exe 等。
六、Java程序(.java文件)先由编译器编译成字节码(.class),由解释器解释执行。
Java的解释过程是通过Java虚拟机读取Java字节码文件(.java),然后将其转换成和系统硬件相关的本地指令(.class),最终在CPU上执行。
解释器在执行字节码文件的过程分为三步:
- 代码的装入
- 代码的校验
- 代码的执行
- 使用javac指令将Java源程序编译成为字节码文件(.class)
- 使用java指令让计算机执行.class文件
- 注意:
- .java文件的文件名和public类名应该相同
- 在用javac时需要带上.java
- 在用java时不需要带上.class
七、两个环境变量(PATH,CLASSPATH)的作用、含义,及其配置——着重理解
-
PATH
SDK平台提供Java编译器(javac.exe)和Java解释器(Java.exe)等位于Java安装包目录的bin文件夹中,为了能够在任何目录中使用编译器和解释器。
-
CLASSPATH
SDK的安装目录jre文件夹中包含着Java运行程序运行时所需要的Java类库,这些类库被包含在jre/lib目录下的压缩文件rt.jar中
八、包的定义(package)、包的导入(import)
Java 程序结构
▪ |包
▪ |----文件
▪ |----------类
▪ |---------------成员(成员变量,方法)
▪ |-----------------------语句
▪ |---------------------------------表达式
Java的package类似于C++的namespace的作用
package a;
public class A{
public void out(){
System.out.println("This is A!");
}
}
package b;
import a.A;
public class B{
public static void main(String[] args){
A a = new A();
a.out();
}
}
Java的语法
考点:
- Java的数据类型:(1)简单:8种,参数传递的是值;(2)复杂:类、接口、枚举、数组,参数传递采用的是引用模型,也就是传地址;
- Java中char采用的是2个字节的unicode编码
- Java采用8个数据类型类对8种基本数据类型进行封装
- Java中的字符串类,String,StringBuffer。String的典型方法:equals(), indexOf()
- Java中的类型转换:自动转换、强制转换。 int age = 1.5;//在Java中是错误的
- Java中的数组的定义,使用。数组的length属性。类的数组的初始化分为两步——如何理解
- Java中带标号的break,continue语句的含义
- 生成随机数数组的例题——消化一下
知识点:
一、标示符的命名:
- 不能是java的保留字;
- 不能数字开头;
- 符号只允许"_“和”$"
- 可以是汉字等unicode字符;
二、Java的数据类型
- 简单数据类型(8种),参数传递的是值。
- byte、short、int、long、char、boolean、float、double
- 表示整数时,以"0"开头为八进制,以"0x"开头为十六进制
- 位数长短:(byte、short、char)–int–long–float–double
- 混合运算时,会自动转换,由字节数低向字节数高转换
- e1+=e2 等价于 e1 = (T1)(e1+e2)
- 强制类型转化时,将浮点型转换成整数型会将小数点后面丢掉
- 复合数据类型:类、接口、枚举、数组、参数传递采用的是引用模型,也就是传地址。
三、保留字
- true、false、null都是小写
- 没有sizeof、const、goto、vitural等,有final
四、Java中的字符串类,String,StringBuffer。String的典型方法:equals(), indexOf()
StringBuffer:线程安全的可变字符序列,类似于String的字符串缓冲区。
字符串时字符组成的序列,分为常量和变量
String s1; // 声明
s1 = new String(); // 初始化
String s1 = new String();// 合并使用
常用方法:
length() //求字符串长度
charAt(int index) //返回第index个字符
indexOf(int ch) //返回字符ch第一次出现的位置,找不到返回-1
indexOf(String str,int index) //第index开始,子串第一次出现的位置,找不到返回-1
subString(int index1,int index2) //返回index1到index2的字串
equals(Object object) // 比较字符串内容和指定对象内容
equalsIgnoreCase(String s) // 比较字符串内容,忽略大小写
== 和 equals()的区别
- 如果是两个基本数值类型
- ==比较的是值
- 如果是String、Integer等重写了equals
- == 比较的是两者是都引用同一个对象,比的是地址
- equals比较的是两者的值
- 其他符合数据类型
- ==和equals一致
五、数组
-
表示一组类型相同的有序数据
-
必须先定义,后使用
-
动态初始化
int[] a = new int[5]; int a[] = new int[5];
-
复合类型数组
String sArray[] = new String[3]; //第一步:声明数组,指定数组名和元素的数据类型 sArray[0] = new String("how"); //第二步:初始化赋值 sArray[1] = new String("are"); sArray[2] = new String("you");
-
length属性是数组类唯一的数据成员变量,new创建数组的时候自动给length赋值
- 在遍历的时候,可以通过i < a.length 方便遍历
- 越界的时候会抛出异常
-
二维数组初始化
//方法1 int a[][]; a = new int[3][4]; //方法2 int a[][] = new int[3][4]; //方法3 int a[][] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}} //方法4 int b[][] = new int[4][]; b[0] = new int[2]; b[1] = new int[4]; b[2] = new int[6]; b[3] = new int[8];
-
深拷贝和浅拷贝
- 浅拷贝,直接拷贝引用,指向同一个地址
- 深拷贝,遍历赋值,指向不同地址
六、带标号的break和continue
要求
- 标号语句必须紧接在循环的头部。标号语句不能用在非循环语句的前面。
- 带标号的break:跳出标号指定的循环,多层循环时可以时任意的外层循环。
- 代表好的continue:终止当前循环,跳过后面的循环体,继续标号对应的那一层的下一轮循环。
public static void main(String[] args) {
search:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 50; j++) {
if (j == 3)
break search;
System.out.println(i+" "+j);
}
}
}
// 输出为:
// 0 0
// 0 1
// 0 2
public static void main(String[] args) {
search:
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 50; j++) {
if (j == 3)
continue search;
System.out.println(i+" "+j);
}
}
}
// 输出为:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
// 1 2
// 2 0
// 2 1
// 2 2
七、生成随机数数组
import java.lang.Math;
public static void main(String[] args) {
Person[] pArray = new Person[5]; //创建长度为5的person数组用于装其子类对象
for (int i = 0;i < 5;i++){
int num = (int)(Math.random()*3); //随机生成1-3的整数,创建相对于的对象类型
switch (num){
case 1:pArray[i] = new Student();break;
case 2:pArray[i] = new Faculty();break;
case 3:pArray[i] = new Staff();break;
}
System.out.println(pArray[i].toString());
}
}
//方法一 new Random()
java.util.Random
public static void main(String[] args)
{
Random r = new Random(1);
for(int i=0 ; i<5 ; i++)
{
int ran1 = r.nextInt(100);
System.out.println(ran1);
}
}
//方法二 Math.random()
java.lang.Math
public static void main(String[] args)
{
int ran2 = (int) (Math.random()*100);
System.out.println(ran2);
}
OOP
考点:
- OOP的三大特征:封装、继承、多态
- 类的定义、类的成员变量、成员方法的定义的语法——一定要掌握
- 如何理解静态变量、静态方法(static)
- 方法的重载和方法的重写(覆盖)的区别。
- 多态:运行时多态、编译时多态
- 运行时多态的两个前提:(1)上溯造型;(2)方法重写(覆盖)
- final关键字修饰 变量、方法、类的时候,分别表示什么含义?
- 抽象类和接口的知识点——重点
- 内部类
- 系统类
知识点:
一、面向对象三大特性
-
封装
- 目的:将对象的使用者和设计者分开
- 在类的定义中设置对对象种的成员变量和方法进行访问的权限
- 提供一个统一供其他类引用的方法
- 其他对象不能直接修改本对象所拥有的属性和方法
-
继承
- 目的:提高代码的复用性,加强类之间的关系,子类沿用父类的特性,同时拥有自己的特性
- 属性的继承
- 方法的继承
- Java只支持单继承
-
多态
-
重载
相同函数名,不同参数和实现
-
覆盖(重写)
相同函数名、参数,不同实现
-
二、类的定义、类的成员变量、成员方法的定义的语法
-
类的定义
[修饰符] class [类名] [extends 父类名][implements 接口名]{ 类体部分 } 修饰符:public、final、abstract、void、static extends:继承某个父类,默认继承自Object类 implements:实现某几个接口
-
类的成员变量定义
- [修饰符] 变量类型 变量名
- 访问修饰符
- default 只有包中可见
- private 只有同一个类中可见
- public 都可见
- protected 只有不同中的非子类不可见
-
成员方法定义
- [修饰符] 返回值类型 方法名(参数列表)[throws 异常列表]
- static:静态方法,类可直接调用
- final:不可重写
- abstract:抽象方法
三、理解静态变量、静态方法(static)
- 静态变量:属于类,而不是属于类创建的对象或实例。静态变量被类的所有实例共用。通常静态变量还和关键字final一起用,作为所有对象共用的资源或常量。如果静态变量不是私有的,那么可以通过ClassName.variableName来访问它.
- 静态方法:静态方法属于类,不属于实例。静态方法只能访问类的静态变量,或调用类的静态方法。通常静态方法作为工具方法,被其它类使用,而不需要创建类的实例
四、构造方法
- 和类同名;
- 无返回值
- 由new调用;
- 可以重载;
- Java为一些没有定义构造函数的类提供无参的构造方法
五、方法的重载和方法的重写(覆盖)的区别。
- 重载:
- 方法名相同,参数不同
- 覆盖(重写):
- 子类重写父类已存在的方法
- 方法名,参数类型相同,返回值类型为父类返回值类型或其子类。
- 访问修饰符的限制大于父类
- 不能抛出比父类大的异常
六、多态
- 编译时多态:重载
- 运行时多态:根据对象的具体类型决定调用什么形式的方法(重写)
- 父类的引用指向子类的地址
七、final关键字
- 修饰变量:常量
- 修饰方法:不能重写
- 修饰类:不能被继承
八、抽象类和接口
-
抽象类
- 用abstract修饰,只能作为父类
- 不能实例化对象
- 抽象类包含的方法不一定是抽象方法,可以有函数体。
- 包含抽象方法的一定是抽象类
- 非抽象子类继承抽象类,必须重写父类所有的抽象方法。
-
抽象方法
- 抽象方法用abstract修饰
- 抽象方法一定不能有方法体
-
接口,类似于(纯虚类)
[访问控制符] interface 接口名{ 抽象方法声明 成员变量声明 }
- 接口不能被实例化
- 所有方法都是抽象方法
- 接口中的变量本质上都是static、final的
- 接口不能继承其他类,可以继承其他接口,一个类可以有多个接口
- 接口不能用private和protected修饰
- 接口引用变量可以指向实例对象
- 一个非抽象子类实现了某个接口,必须重写里面的所有抽象方法
九、内部类
- 成员内部类不能有static属性和static方法
- 内部类可以是静态的
- 成员内部类可以无障碍访问外部类的任何成员
- 优势:内部类可以独立继承接口,对外围类没有影响,这使得多重继承的解决更加完美
十、对象实例化过程
- 内存分配:
- 初始化顺序
- 先static
- 先父类后子类
- 先变量后方法
十一、系统类
Object的常用方法
-
equals
- 如果不是String这些重写过这个方法的类,就是比较是否是同一个引用
-
getClass
- 返回类运行时的Class
-
toString
-
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
-
-
Class类实现Java的反射特性
Class c = Class.forName("MyClass"); MyClass mc = (MyClass)c.newInstance();
基本数据类型和String的转换
s = num + "";
s = Integer.toString(num);
s = String.valueOf(num);
num = Integer.parseInt(s);
Integer.valueOf(s).intValue();
动态数组Vector,ArrayList的使用
-
相同与区别
- 两者内部都是通过数组实现的,存储空间上连续
- Vector支持线程的同步,因此避免多线程导致的不一致性,但是降低访问速率
- 都有初始大小,如果元素超过初始大小时,Vector容量翻倍,ArrayList增加50%
-
Vector用法
import java.util.*; public static void main(String args[]) { // initial size is 3, increment is 2 Vector v = new Vector(); v.add(1); v.add(3); System.out.println("First element: " + (Integer)v.firstElement()); System.out.println("Last element: " + (Integer)v.lastElement()); if(v.contains(3) System.out.println("Vector contains 3."); System.out.println("Current capacity: " + v.capacity()); Enumeration vEnum = v.elements(); while(vEnum.hasMoreElements()) System.out.print(vEnum.nextElement() + " "); }
-
ArrayList用法
import java.util.ArrayList; public class RunoobTest { public static void main(String[] args) { ArrayList<String> sites = new ArrayList<String>(); sites.add("Google"); sites.add("Runoob"); sites.set(0,'Run'); //将第一个元素修改为Run sites.remove(1); //删除第二个元素 System.out.println(sites); } } // [Run]
异常处理
考点:
- Java的异常处理的基本概念
- 理解JVM中的运行错误和Java的异常类之间的对应关系(由JVM帮我们对应);
- 掌握PPT中关于异常的那张图(异常产生、传递、处理的流程图)
- Java中异常类的分类:运行时异常、非运行时异常,分类标准时什么,分类的目的是什么?
- 异常的两种处理方法:(1)try-catch(重点);(2)在函数头部声明
- 自定义异常——了解一下:throw与throws的区别
知识点:
一、异常处理基本概念
-
异常的定义
指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。
-
优势:
使完成正常功能的程序代码与进行异常处理的程序代码分开。
-
Java处理异常的两种方法:
- 在发生异常的地方直接处理
- 将异常抛给调用者,让调用者处理
-
异常的分类——Exception(异常)和Error(错误)
- Exception程序本身及环境所产生的异常
- Error处理内部系统错误
二、JVM运行错误和Java异常类之间的对应关系
- 程序执行中如果出现异常,系统会检测到并自动生成一个相应的异常类对象,然后交给运行时系统
- 运行时系统自动寻找对应的异常处理代码来处理这一异常。如果找不到可处理该异常的代码,程序会终止
三、异常处理的流程
四、异常类的分类
-
运行时异常
运行时异常都是RuntimeException类及其子类异常,如NullPointerException、IndexOutOfBoundsException等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。
-
非运行时异常
非运行时异常是RuntimeException以外的异常,类型上都属于Exception类及其子类。如IOException、SQLException等以及用户自定义的Exception异常。对于这种异常,JAVA编译器强制要求我们必需对出现的这些异常进行catch并处理,否则程序就不能编译通过。所以,面对这种异常不管我们是否愿意,只能自己去写一大堆catch块去处理可能的异常。
-
异常类的常用函数(输出异常的基本信息)
- toString()
- getMessage()
- printStackTrace() //异常的传递轨迹
五、异常处理方法
-
直接捕获
public class CatchDemo{ public static void main(String[] a){ method(1); method(2); } static void method(int i){ try{ if(i == 1){ int b = 3/0 //抛出异常ArithmeticException }else if(i == 2){ int c[] = new int[3]; c[5] = 3; //抛出异常ArrayIndexOutOfBoundsException } }catch(ArithmeticException e){ System.out.println(e); }catch(ArrayIndexOutOfBoundsException e){ System.out.println(e); } } }
-
函数头抛出
public class CatchDemo{ public static void main(String[] a){ try{ method(1); method(2); }catch(ArithmeticException e){ System.out.println(e); }catch(ArrayIndexOutOfBoundsException e){ System.out.println(e); } } static void method(int i) throws ArithmeticException,ArrayIndexOutOfBoundsException{ if(i == 1){ int b = 3/0 //抛出异常ArithmeticException }else if(i == 2){ int c[] = new int[3]; c[5] = 3; //抛出异常ArrayIndexOutOfBoundsException } } }
六、自定义异常
- 目的:查出自定义的业务逻辑错误
- 如何实现
- 定义异常类
- 创建、抛出异常类的对象
class MyException extends Exception{
MyException(String s){
super(s);
}
}
if(age < 0){
throw new MyException("用户年龄不能小于0");
}
- throws和throw的区别
- throws用于方法头,表示异常的申明,throw用于方法体,抛出的是异常对象
- throws可以抛出多个异常,throw只能抛出一个
- throws抛出异常,它的调用者要申明捕获异常,否则报错。throw可以不申明。
输入输出流
考点:
- 输入输出流分为四大类,四个抽象类分别是什么,什么含义?
- 会用字节流、字符流编写文件的拷贝程序
- 掌握File的用法
- 掌握字节流到字符流转换器:InputStreamReader, OutputStreamWriter
- 会用BufferedReader,BufferedWriter
知识点:
一、输入输出流四大类
- 输入字节流
- InputStream
- 输入字符流
- Reader
- 输出字节流
- OutputStream
- 输出字符流
- Writer
二、会用字节流、字符流表现捏文件的拷贝程序
-
文件读写类
- FileInputStream
- FileOutputStream
- FileReader
- FileWriter
-
File类
-
构造方法:
File(String pathOrName); File(String path,String name); File(File dir,String name);
-
成员方法:
String getName() getPath() getParent() getAbsolutePath() boolean renameTo(File newName) boolean exists() canWrite() canRead() long length()
-
-
使用FileInputStream和FileOutPutStream完成文件拷贝
void copy(String srcFile,String dstFile) throws Exception{ InputSteam input = new FileInputStream(srcFile); OutputStream output = new FileOutputStream(dstFile); byte[] buf = new byte[256]; int length = 0; while((length = input.read(buf)) != -1){ output.write(buf,0,length); } output.flush(); input.close(); output.close(); }
-
FileReader和FileWriter完成文件拷贝
void copy(String srcFile,String dstFile) throws Exception{ FileReader reader = new FileReader(new File(srcFile)); FileWriter writer = new FileWriter(new File(dstFile)); char[] buf = new char[256]; int length = 0; while((length = reader.read(buf)) != -1){ writer.write(buf,0,length); } writer.flush; reader.close(); writer.close(); }
-
字节流转化成字符流(这样可以自定义文件的字符集)
void copy(String srcFile,String dstFile) throws Exception{ InputSteam input = new FileInputStream(srcFile); OutputStream output = new FileOutputStream(dstFile); Reader reader = new InputStreamReader(input,"GBK"); Writer writer = new OutputStreamWriter(outpu t,"GBK"); char[] buf = new char[256]; int length = 0; while((length = reader.read(buf) != -1)){ writer.write(buf,0,length); } writer.flush; reader.close(); writer.close(); }
三、缓冲流
-
FilterInputStream,FilterOutputStream
-
缓冲字符流:BufferedReader/BufferedWriter
-
优势
- 提供缓冲功能,读写效率更高
- 提供更方便的API函数,读写字符:String readLine()可以直接读取文件的一行并返回
-
import java.io.*; InputStream is = new FileInputStream("..."); //得到文件字节流 Reader r = new InputStreamReader(is,"GBK"); //封装成字符流 BufferedReader br = new BufferedReader(r); //封装成字符过滤流 //三合一 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("in.txt"))); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out.txt"))); String line = ''; while((line = br.readLine()) != null){ bw.write(line + "\n"); } bw.flush(); br.close(); bw.close();
多线程
考点:
- Thread,Runnable是Java多线程编程中最重要的类、接口
- 多线程的四种状态图;
- 两种编写多线程程序的方法——要会写代码。理解两种方法的区别、优缺点
- 了解Java中临界资源的同步,使用synchronized关键字
- 线程的Thread.sleep(), Thread.currentThread()获得当前正在运行线程
知识点:
一、Thread类、Runnable接口
二、线程的四种状态图
-
创建状态
Thread t = new Thread() //处于创建状态的线程对象,只能作启动、终止线程操作(start()、stop())。
-
可运行状态
Thread t = new Thread(); t.start(); t.yield(); //让步,放弃当前CPU使用权,但马上竞争新的CPU //start()方法产生线程运行所需要的系统资源,并将线程提交给Java的线程调度器,等待执行。
-
不可运行状态
Thread t = new Thread(); t.sleep(300) //休眠300ms,到时间后自动启动 t.wait(); //挂起,需要notify来唤醒 t.notify() //唤醒线程
-
死亡状态
Thread t = new Thread(); t.run(); //run方法结束之后,正常死亡 t.stop(); //非正常死亡
三、两种创建线程的方法
方式一:继承Thread类
public class MyThread extends Thread{
@Override
public void run(){
//重写run方法
for(int i = 0;i < 10;i++){
System.out.println(i);
}
}
public static void main(String[] args){
//创建线程实例
MyThread myThread = new MyThread();
myThread.start(); //start方法会调用run()方法
}
}
- 程序书写简单,但是不能再继承别的类。
方式二:实现Runnable接口
public class MyThread implements Runnable{
@Override
public void run(){
//重写run方法
for(int i = 0;i < 10;i++){
System.out.println(i);
}
}
public static void main(String[] args){
Thread td = new Thread(new MyThread());
td.start();
}
}
- 可以将Thread对象、代码和实现Runnable接口的类分开
- 可以实现多个接口
四、临界资源的同步(synchronized)
- 在调用synchronized时,对象会被锁定
- 当synchronized方法执行完或发生异常时,会自动释放锁
- 被synchronized保护的数据应该是私有的
class Cbank {
private static int s=1000; //银行存款
//使用synchronized保证资源同步
public synchronized static void sub(int m){
int temp = s;
temp = temp - m; //取钱之后的钱
try{
Thread.sleep((int)(1000*Math.random()));
}catch(InterruptedException e){ }
s= temp;
System.out.println("s = "+s);
}
}
class Customer extends Thread {
public void run(){
for(int i=1; i<=5; i++)
Cbank.sub(100); //取100块钱
}
}
//main class
class Thread {
public static void main(String args[]){
Customer c1 = new Customer();
Customer c2 = new Customer();
c1.start();
c2.start();
}
}
网络通信
考点:
- URL类的使用,InputStream openStream()会使用字节流、URL类下载网上的文件资源——会编程
- 重点:理解Socket通信的模型、原理;掌握ServerSocket、Socket类的用法;基于Socket的网络通信程序的编写(结合实验三)
知识点总结:
一、URL类的使用
URL是Java提供的网络功能中最高级的一种,通过URL可以直接读写网络上的数据
-
URL的组成:http://61.135.169.125:80/img/baidu_sylogo1.gif
- 资源类型:http
- 主机域名:61.135.169.125 (www.baidu.com)
- 端口:80
- 资源文件名:/img/baidu_sylogo1.gif
-
HTTP默认端口80,FTP默认端口21,HTTPS默认端口43
-
URL类的构造方法
URL类的构造方法 功能说明 public URL(String str) 使用URL字符串创建URL对象 public URL(String protocol,String host,String file) 通过指定协议名、主机名、文件名,端口使用默认值,创建URL对象 public URL(String protocol,String host,String port,String file) 通过指定协议名、主机名、文件名和端口号,创建URL对象 public URL(URL content,String str) 通过在已知的URL路径上增加细节的办法创建URL对象 -
URL类的方法
URL 类 功能说明 int getPort() 获得端口号,如果端口没有设置,返回-1 String getProtocol() 获得协议名,如果协议没有设置,返回null String getHost() 获得主机名,如果主机没有设置,返回null String getFile() 获得文件名,如果文件没有设置,返回null Boolean equals(Object obj) 与指定的URL对象obj 进行比较,如果相同返回true,否则返回false Final OpenStream() 获得一个输入流,若获取失败,则抛出一个java.io.Exception异常 String toString() 将此URL对象转换为字符串的形式 -
使用URL类读取网页数据
-
URL数据-> InputStreamReader对象 -> BufferedReader对象
import java.net.*; import java.io.*; public class Network_1{ public static void main(String[] args) throws Exception{ URL hfut = new URL("http://www.baidu.com"); BufferedReader in = new BufferedReader(new InputStreamReader( hfut.openStream() ) ); String inputLine; //打印输出HTML while ( (inputLine = in.readLine() ) != null ) System.out.println(inputLine); //关闭缓冲区 in.close(); } }
-
URL对象-> URLConnection对象 -> InputStreamReader ->BufferedReader
import java.net.*; import java.io.*; public class Network_2 { public static void main(String[] args) throws Exception { URL hfut = new URL("http://www.baidu.com"); URLConnection uc = hfut.openConnection(); BufferedReader in = new BufferedReader(new InputStreamReader( uc.getInputStream())); String inputLine; while ((inputLine = in.readLine()) != null) System.out.println(inputLine); in.close(); } }
-
二、Socket通信模型、原理
-
定义:
-
网络上运行的程序之间双向通信链路的最后终结点。
-
IP与端口的组合得出的套接字。
-
-
模型、过程:
-
原理:
-
服务器端:Server
- ServerSocket:监听本机端口
- Socket:连接客户端
- PrintWriter:向客户端传输数据
- BufferedReader:读取客户端传入的数据
-
客户端:Client
- Socket:连接服务器
- BufferedReader:读入本地用户命令行输入
- PrintWriter:向服务器传输数据
-
Socket和ServerSocket用法:
import java.net.*;
import java.io.*;
public class Server {
public static void main(String[] args) throws IOException {
// 创建服务器端实例server,设置端口80
try {
ServerSocket server = new ServerSocket(80);
} catch (IOException e) {
System.exit(1);
}
try {
//通过ServerSocket的方法accept自动创建Socket实例
Socket client = server.accept();
//通过PrintWriter实例将信息发送给客户端
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
//通过BufferedReader接收客户端信息
BufferedReader in = new BufferedReader(new InputStreamReader
(client.getInputStream()));
} catch (IOException e) {
System.exit(1);
}
while (true) {
String line = in.readLine();
String len = line.length(); // 计算客户端发来信息长度
//告诉客户端发来的信息有多长
out.println("received string's length is: "+ strlen);
if(line.equalsIgnoreCase("Bye"))
break;
}
out.close();
in.close();
client.close();
server.close();
}
}
//client
import java.io.*;
import java.net.*;
public class Client {
public static void main(String[] args) throws IOException {
try {
//实例化客户端,设置端口80,和本地IP
Socket client = new Socket("127.0.0.1", 80);
//通过PrintWriter实例将信息发送给服务器端
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
//通过BufferedReader实例接收服务端信息
BufferedReader in = new BufferedReader(new InputStreamReader
(client.getInputStream()));
} catch (Exception e) {
System.exit(1);
}
BufferedReader stdIn = new BufferedReader(
new InputStreamReader(System.in));
while (true){
String line = stdIn.readLine();// 读取命令行输入的信息
out.println(line);// 将命令行内容发送给服务器端
if(line.equalsIgnoreCase("Bye"))
break;
}
out.close();
in.close();
stdIn.close();
}
}
GUI
考点:
- 掌握常用的容器Frame,Panel的使用,知道四种容器:
- Window,Frame —— 默认布局BorderLayout
- Panel,Applet —— 默认布局FlowLayout
- 容器的最常用的方法
- add()
- setLayout()
- setSize()
- setVisible()
- 掌握基本的GUI组件的使用:
- Label
- Button
- TextField
- TextArea
- Choice
- …
- AWT事件监听模型,PPT那张图、那张表要掌握。
- 以ActionEvent为例,自己编写一个按钮的消息响应代码(实验三全部包含)。
知识点总结:
一、掌握常用的容器Frame,Panel的使用,知道四种容器
-
定义:容器就是组件放置的地方。其本身可以看成是一个特殊的组件,只不过可以容纳其他的组件或容器。
-
四者关系:一般就用Frame(窗体)和Panel
-
布局方式(可以用途serLayout修改布局方式):
- FlowLayout(Pannel、Applet默认)
- 从左向右,排满后换行
- 各行居中
- BorderLayout(Window、Frame默认)
- 分为东西南北中五块
- East,West,South,North
- CardLayout
- 类似于轮播图
- GridLayout
- 将窗体划分为若干网格
- FlowLayout(Pannel、Applet默认)
二、容器的最常用的方法
- add() --> 容器中添加组件
- setLayout() --> 设置布局方式
- setSize() --> 设置尺寸大小
- setVisible() --> 设置是否可见
- setBackground --> 设置组件的背景颜色。
- setDefaultCloseOperation() --> 设置窗口默认处理方法(swing独有)
- setTitle() --> 设置窗口中标题栏的文字
- setResizable() --> 设置用户是否可以改变框架大小
- setPreferredSize() --> 设置组件的大小尺寸
三、掌握基本的GUI组件使用
-
Label–文本
Label titleLabel = new Label("服务器设置"); titleLabel.setPreferredSize(new Dimension(380,30));
-
Button–按钮
Button sayButton = new Button("Say");
-
TextField–输入框
TextField portText = new TextField(); //输入框 startButton.addActionListener((e)->{ server = new Server(Integer.parseInt(portText.getText()),textArea); });
-
TextArea–文本框
TextArea textArea = new TextArea(); textArea.setPreferredSize(new Dimension(380,100));
-
Choice–下拉框
//下拉选择框 Choice choice1 = new Choice(); choice1.add("下拉框1"); choice1.add("下拉框2");
四、AWT事件监听模型
- 事件源:描述人机交互中时间的来源,通常是Java图形包的组件
- 事件:事件源产生的交互内容,如:“按下鼠标”,java.awt.event中的类
- 事件监听器:接收事件并进行处理,由程序员编写对应处理所监听事件源产生的事件
- 监听器接口:编写"事件监听器"的"规定"—"抽象方法"必须在监听器类中实现这些方法完成事件处理
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e){
// 按钮事件所进行的具体工作
}
}
常用事件类:
事件类型 | 典型触发动作 |
---|---|
ActionEvent | 按钮、列表双击、单击菜单项目 |
KeyEvent | 键盘的输入 |
MouseEvent | 鼠标拖动、移动、单击、按下、释放或者进入、退出组件的事件 |
ComponentEvent | 组件被隐藏、移动、尺寸调整或变为不可见的事件 |
FocusEvent | 组件获得或失去焦点的事件 |
InputEvent | 复选框和列表项单击、控件的选择和可选菜单项的选择事件 |
TextEvent | 文本区域或者文本区域的值的改动 |
WindowEvent | 窗口激活、失去活动窗口、最小化、最小化、打开、关闭或者退出的事件 |
事件处理接口:
事件类型 | 典型触发动作 |
---|---|
ActionListener | 处理按钮、列表双击、单击菜单项目 |
KeyListener | 处理键盘的输入 |
MouseListener | 处理鼠标拖动、移动、单击、按下、释放或者进入、退出组件的事件 |
ComponentListener | 处理组件被隐藏、移动、尺寸调整或者变为不可见的事件 |
FocusListener | 处理组件获得或失去焦点的事件 |
TextListener | 处理文本区域或者文本区域的值的改动 |
WindowListener | 处理窗口激活、失去活动窗口、最小化、最小化、打开、关闭或者退出的事件 |
- 将监听器绑定到组件:通过addXXXListener方法
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.event.ActionListener;
public class Main {
public static void main(String[] args) {
myButtonFrame frm = new myButtonFrame("ActionEventTest");
frm.show(); //显示窗体
}
}
//设计窗口类
class myButtonFrame extends Frame{
JButton btn;
//构造函数
myButtonFrame(String s){
super(s);
this.setSize(200,120);
//创建按钮
btn = new JButton("按钮");
this.add(btn);
btn.addActionListener(new buttonListener());
}
//监听器类
class buttonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e){
System.out.println("你已经按下按钮了");
}
}
}