文章目录
Java面向对象程序设计
第一章 Java开发入门
Java语言的优点
- 简洁性
- 面向对象性
- 安全性
- 跨平台性
- 支持多线程
什么是JDK?:SUN公司提供的一套Java开发环境,是整个java的核心,包括Java编译器、Java运行工具、Java文档生成工具、Java打包工具等
JDK安装目录介绍
- bin目录:用于存放一些可执行程序,最重要的是javac.exe和java.exe
- db目录:db目录是一个小型的数据库
- jre目录:java运行环境的根目录,包含Java虚拟机、运行时的类包、Java应用启动器以及一个bin目录,但不包含开发环境的开发工具
- include目录:jdk是用C/C++实现的,需要引入一些头文件,该目录就是用于存放头文件的
- lib目录:开发工具使用的归档包文件
- src.zip:src文件夹的压缩文件,src中放置的是jdk核心类的源代码,通过该文件可以查看java基础类的源代码
用命令窗口开发java程序
-
编写Java源文件
-
打开命令行窗口
-
进入JDK安装目录的bin目录
cd c:\Program Files\Java\jdk.1.7.0_60\bin
-
编译Java源文件
javac helloworld.java
-
运行java程序
java helloworld
两个系统环境变量:path和classpath
有点多,自己看书吧,应该不是重点,了解一下就行,下一章走起!
(考)JVM工作原理
编译成功之后,会直接生成一个.class字节码文件
运行Java虚拟机之后,Java虚拟机首先将编译好的字节码文件加载到内存,这个过程叫做类加载,它是由类加载器完成的。然后虚拟机根据加载到内存中的java类进行解释执行。便可看到运行结果。
好处:在java虚拟机执行java程序,可以实现跨平台,“一次编写,到处运行”,有效解决了程序设计语言在不同操作系统编译时产生不同机器代码的问题。但不同的操作系统对应的java虚拟机也不相同
第二章 Java编程基础
Java的基本语法
修饰符 class 类名{
程序代码
}
eg:
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
//然后就可以自己对应格式去理解
Java中的注释
1、单行注释
int c = 10; //单行注释
2、多行注释
/*int a = 11;
a = 199;*/
Java中的标识符
由字母、数字、下划线组成,但不能以数字开头,同时不能是Java中提到的那些关键字(规则和其他语言差不多)
Java中的常量
- 整型常量
- 浮点数常量
- 字符常量
- 字符串常量
- 布尔常量
- null常量(空)
变量的数据类型
变量的转换类型
-
自动类型转换
隐式类型转换(两种数据类型兼容,目标类型的取值范围大于源类型的取值范围)
public class Main { public static void main(String[] args) { byte a = 10; int b = a;//自动转换 } }
-
强制类型转换
显式类型转换(当两种类型不兼容,或目标类型的取值范围小于源类型的取值范围)
public class Main { public static void main(String[] args) { int a = 10; byte b = (byte)a;//强制转换 } }
运算符
- 算术运算符(加减乘除等)
- 赋值运算符(=,+=,-=,/=,%=等)
- 比较运算符(==,!=,<,>等)
- 逻辑运算符(&,|,^,!,&&,||)
运算符的优先级(书上查找,非重点)
方法:一段可以重复调用的代码
数组的定义
1、int[] x = new int[100];
2、int[] x = {1,2,3,4,5};
3、int[] x;
x = new int[100];
元素默认值(应该是重点,还是要看一下)
- 默认初始化为0:byte,short,int,long
- 默认初始化为0.0:float,double
- 默认初始化为一个空字符(‘\u0000’):char
- 默认初始化为false:boolen
- 默认初始化为null,表示不引用任何对象:引用数据类型(String,Integer……)
数组常见操作
数组遍历
public class Main {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
数组最值
public class Main {
public static void main(String[] args) {
int[] arr = {4,5,6,3,28};
int m = arr[0];
for(int i = 1;i<arr.length;i++){
m = Math.max(m,arr[i]);
}
System.out.println(m);
}
}
数组排序
public class Main {
public static void main(String[] args) {
int[] arr = {4,5,6,3,28};
System.out.println("排序前……");
printArray(arr);
bubbleSort(arr);
System.out.println("排序后……");
printArray(arr);
}
public static void printArray(int[] arr){
for(int i = 0;i<arr.length;i++){
System.out.println(arr[i]+" ");
}
}
//用冒泡排序法排序
public static void bubbleSort(int[] arr){
for(int i = 0;i<arr.length-1;i++){
for(int j = 0;j<arr.length-i-1;j++){
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
多维数组就自己去看看吧,和一维数组一个意思
第三章 面向对象(上)
面向对象的三大特性
- 封装性
- 继承性
- 多态性
类的定义
class Person{
int age;//定义成员变量
//定义成员方法
void speak(){
System.out.println("大家好,我今年"+age+"岁");
}
}
注意:定义在类中的变量是成员变量,定义在方法中的变量是局部变量
对象的创建与使用
//类名 对象名称 = new 类名();实质是调用类中的构造方法初始化对象,无参数就调用无参构造器,有参数就调用有参构造器
Person p = new Person();
类的封装
在设计一个类的时候,应该对成员变量的访问做出一些限定,不允许外界随意访问,这就需要实现类的封装。在定义一个类的时候,将类中的属性私有化,即用private关键字来修饰私有属性只能在它所在类中被访问。当外界想访问的时候,可以提供一些public方法,如getXXX和setXXX方法
构造方法
定义:方法名与类名相同,在方法名的前面没有返回值类型的声明(如void,int),在方法中不能使用return语句返回值,但是可以单独写return语句来作为方法的结束
构造方法的重载
//利用构造方法的参数个数和参数类型不同,或者是参数本身不同,来实现方法的重载,在调用的时候根据参数的不同,来调用不同的构造方法,更灵活
//!!!如果不定义任何构造函数,那么构造函数就默认调用系统创建的无参构造器,同时不进行任何操作,只是用作建立一个新对象
class Person{
String name;
int age;
public Person(){
}
public Person(String name){
}
public Person(int age){
}
public Person(String name,int age){
}
}
this关键字
我表示这东西我书面解释不清楚,那就直接看例子自己摸索吧
三种常见用法 (this大概就是调用这个方法的那个对象吧,哪个调用它,this就代表哪个)
//通过this关键字可以明确的访问一个类的成员变量,解决与局部变量名称冲突问题
class Person{
int age;
public Person(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
//通过this关键字调用成员方法
class Person{
public void openMouth(){
}
public void speak(){
this.openMouth();
}
}
//构造方法实在实例化对象时被Java虚拟机自动调用的,在程序中不能像调用其他方法去调用构造方法,但可以在构造方法中用this([参数])的方法来调用其他的构造方法
class Person{
public Person(){
System.out.println("无参调用");
}
public Person(String name){
this();//用this关键字调用无参构造器实现构造新对象,this()位于第一行
System.out.println("有参调用");
}
}
注意:
- 只能在构造方法中使用this调用其他的构造方法,不能在成员方法中调用
- 在构造方法中,使用this关键字调用构造方法的语句必须位于第一行,且只能出现一次
- 不能在一个类的两个构造方法中使用this互相调用
super关键字
(为了体现this和super的对比,在此提前总结super关键字)
super关键字用于访问父类的成员变量、成员方法和构造方法
//super.成员变量
//super.成员方法([参数])
//使用super关键字访问父类的构造方法
super([参数])
在子类的构造方法中一定会调用父类的某个构造方法,这时可以在子类的构造方法中通过super指定调用父类的哪个构造方法
(考)this和super的对比
this指的是调用本类对应的对象,super指的是本类的父类
垃圾回收
当内存不足时,虚拟机会自动释放不需要的垃圾。除了等待虚拟机释放内存,也可以手动调用System.gc()方法来通知虚拟机立即回收垃圾。当一个对象在内存中被释放时,它的finalize()方法会被自动调用,因此可以在类中定义finalize()方法来观察对象何时被释放
static关键字
在java类中,可以使用static关键字来修饰成员变量,该变量被称作静态变量,静态变量被所有实例共享,在内存中只有一份。用"类名.变量名"或者"对象名+变量名"的形式访问。但是注意:static关键字只能用于修饰成员变量,不能用于修饰局部变量,否则报错
静态方法:和静态方法一样,用"类名+方法名"或者"对象名+方法名"来访问
public class Main {
public static void main(String[] args) {
Person.sayHello();//通过类名访问静态方法
Person p= new Person();
p.sayHello();//也可以用具体对象调用静态方法
}
}
class Person{
public static void sayHello(){
System.out.println("hello");
}
}
注意:在一个静态方法中只能访问用static修饰的成员,原因在于没有被static修饰的成员需要先创建对象才能访问,而静态方法在被调用时可以不创建任何对象
静态代码块:用一对大括号包围起来的若干行代码被称为一个代码块,用static修饰的代码块被称为静态代码块
class person{
static{
//静态代码块
}
}
成员内部类
在一个类中定义的类叫做成员内部类,在成员内部类中,可以访问外部类的所有成员
public class Main {
public static void main(String[] args) {
Outter outter = new Outter();
outter.test();
}
}
class Outter{
private int num = 4;
public void test(){
Inner inner = new Inner();
inner.show();
}
class Inner {
void show(){
//statement
}
}
}
如果想通过外部类去访问内部类,则需要通过外部类对象去创建内部类对象
public class Main {
public static void main(String[] args) {
Outter.Inner inner = new Outter().Inner();
inner.show();
}
}
class Outter{
private int num = 4;
public void test(){
Inner inner = new Inner();
inner.show();
}
class Inner {
void show(){
//statement
}
}
}
第四章 面向对象(下)
类的继承
- java只支持单继承
- 多个类可以继承一个父类
- 支持多层继承
- 子类和父类是相对的
final关键字
- final修饰的类不能被继承
- final修饰的方法不能被子类重写
- final修饰的变量(成员变量和局部变量)是常量,只能赋值一次
抽象类和接口
-
抽象类
abstract void show();//定义抽象类
当一个类中定义了抽象方法,该类也必须用abstract修饰,即抽象方法;但是抽象类可以不包含抽象方法
抽象类不可以被实例化对象
abstract class Animal{ abstract void shout(); } class Dog extends Animal{ void shout(){ System.out.println("汪汪汪……");//在子类中将抽象类的抽象方法shout()实现 } }
-
接口
由常量和抽象方法组成的特殊类,对抽象类的进一步抽象
[public] interface 接口名 [extends 接口1,接口2……]{ [public] [static] [final] 数据类型 常量名 = 常量值; [public] [abstract] 返回值 抽象方法名(参数列表); }
例子:
interface Animal{ String ANIMAL_BEHAVIOR = "动物的行为"; void breathe(); void run(); } class Dog implements Animal{ public void breathe(){ System.out.println(ANIMAL_BEHAVIOR+"狗在呼吸"); } public void run(){ System.out.println(ANIMAL_BEHAVIOR+"狗在跑"); } } public class main{ public static void main(String args[]){ Dog dog = new Dog(); dog.breathe(); dog.run(); } }
接口中的变量默认使用public static final修饰
接口中定义的方法默认使用public abstract修饰
注意:一个类如果要实现一个接口,必须要给出接口中所有方法的实现,如果不能给出实现,也必须写出一个空方法。
总结:
-
接口中的方法都是抽象的,不能实例化对象
-
接口中的属性只能是常量
-
当一个类实现接口时,如果这个类是抽象类,则实现接口中的部分方法即可,否则需要实现全部方法
-
一个类通过implements关键字实现接口时,可以实现多个接口,被实现的接口用逗号隔开
-
一个接口可以通过extends关键字继承多个接口,接口之间用逗号隔开
-
一个类在继承另一个类的同时还可以实现接口,此时,extends关键字必须位于implements关键字之前
class Dog extends Canidae implements Animal{ //statement }
-
多态(多态就是一种思想,具体的没有啥知识点)
java提供了一个关键字instanceof,它可以判断一个对象是否为某个类的实例或子类实例
对象(或者对象引用变量) instanceof 类(或接口)
Object类:所有对象的根类
提供的方法:
- equals():指示其他某个对象是否与此对象相等
- getClass():返回此对象的运行时类
- hashCode():返回该对象的哈希码值
- toString():返回该对象的字符串表示
//toString()方法的结构:
getClass().getName()+"@"+Integer.toHexString(hashCode());
匿名内部类:
new 父类(参数列表)或父接口(){
//实现
}
异常
异常类的结构
-
Error代表程序中产生的错误
仅靠修改程序本身不能恢复执行,比较严重的
-
Exception代表程序中产生的异常
程序本身可以处理的错误,其中的子类RuntimeException及其子类表示运行时异常,而其他的子类都是表示编译时异常
常用方法:
- String getMessage():返回此throwable 的详细消息字符串
- void printStackTrace():将此throwable及其追踪输出至标准错误流
- void printStackTrace(PrintStream s):将此throwable及其追踪输出到指定的输出流
try···catch 和finally
try{
//程序代码块
}catch(ExceptionType e){
//对异常的处理
}
eg:
public class Main {
public static void main(String[] args) {
try{
int result = divide(4,0);
System.out.println(result);
}catch (Exception e){
System.out.println(e.getMessage());
}
System.out.println("程序详细向下执行……");
}
public static int divide(int x,int y){
int result = x/y;
return result;
}
}
throws关键字
public class Main {
public static void main(String[] args) {
try{
int result = divide(4,0);
System.out.println(result);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("程序详细向下执行……");
}
public static int divide(int x,int y)throws Exception{
int result = x/y;
return result;
}
}
自定义异常:
public class Main {
public static void main(String[] args) {
try {
int result = divide(4,-2);
System.out.println(result);
}catch (DivideByMinusException e){
System.out.println(e.getMessage());
}
}
public static int divide (int x,int y) throws DivideByMinusException{
if(y<0){
//使用throw关键字声明异常
throw new DivideByMinusException("除数为负数");
}
int result = x/y;
return result;
}
}
class DivideByMinusException extends Exception{
public DivideByMinusException(){
super();
}
public DivideByMinusException(String message){
super(message);
}
}
注意:当方法用throws关键字抛出异常后,调用该方法就要用try catch语句捕获异常
(可能考)面向对象程序设计中动态绑定技术的必要条件
这个我不知道讲没讲,但是可能会考!
(1) 只有虚函数才能进行动态绑定,非虚函数不进行动态绑定。
(2) 必须通过基类类型的引用或指针进行函数调用。
然后后面的几章就自己看书了解吧,我只把可能会考到的列出来
第五章 Java API
(考)Lamda表达式的语法及应用
Lambda表达式格式:()->{}
1.小括号中书写的内容和接口中的抽象方法的参数列表一致
2.大括号中书写的内容和实现接口中的抽象方法体一致
3.箭头是固定的
Lambda表达式只能实现函数式接口,并且接口中只有一个抽象方法
类型:
-
变量的形式:变量的类型为函数式接口,就么可以复制一个Lambda表达式【不常用】
// 变量的形式 Runnable r = ()->{ System.out.println("任务代码"); }; // 函数式接口类型的变量 Thread t = new Thread(r);
-
参数的形式:方法的形参类型为函数式接口,就可以传入一个Lambda表达式【常用】
// 变量的形式-比较器 Comparator<Integer> comparable = (o1, o2)->{return o2 - o1;}; // 创建集合 ArrayList<Integer> list = new ArrayList<>(); // 存入数据 Collections.addAll(list,11,22,33,44,55); // 将函数式接口类型 的 形参类型,传给Collections Collections.sort(list,comparable);
-
返回值的形式:方法的返回值类型为函数式接口,就可以返回一个Lambda表达式【常用】
// 定义一个方法 public static Comparator<Integer> getComparator(){ return (Integer o1,Integer o2)->{return o2-o1;}; } public static void main (String[] args) { // 返回值形式 Collections.sort(list,getComparator()); }
第六章 集合类
Collection框架:
Map框架:
Collection接口的常用方法
- boolean add(Object o):向集合中添加一个元素
- boolean addAll(Collection c):将指定Collection中所有元素添加到该集合中
- void clear():删除该集合中的所有元素
- boolean remove(Object o):删除该集合中指定的元素
- booean removeAll(Collection c):删除指定集合中所有的元素
- boolean isEmpty():判断该集合是否为空
- boolean contains(Object o): 判断该集合中是否包含某个元素
- boolean containsAll(Collection c):判断该集合中是否包含指定集合中所有的元素
- Iterator iterator():返回在该集合的元素上进行迭代的迭代器(Iterator),用于遍历该集合所有元素
- int size():获取该集合中元素个数
Map接口的常用方法
- void put(Object key,Object value):将指定的值与此映射中的指定键关联
- Object get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null
- boolean containsKey(Object key):如果此映射包含指定键的映射关系,则返回true
- boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回true
- Set keySet():返回此映射中包含的键的Set视图
- Collection<V> values():返回此映射中包含的值的Collection视图
- Set<Map.Entry<K,V>> entrySet():返回此映射中包含的映射关系的Set视图
泛型:限制集合中元素的类型,如Collection<String>代表集合中只能添加String类型的元素
Arrays,Collections,Iterator,Comparable,Comparator的典型案例就在书上找吧
第七章 IO(输入输出)
IO框架
File类
File类的常用方法
- File(String pathname):通过指定的一个字符串类型的文件路径来创建一个新的File对象
- File(String parent,String child):根据指定的一个字符串类型的父路径和一个字符串类型的子路径(包括文件名称)创建一个File对象
- File(File parent,String child):根据指定的File类的父路径和字符串类型的子路径(包括文件名称)创建一个File对象
- boolean exists():判断File对象对应的文件或目录是否存在,若存在则返回true,否则false
- boolean delete():删除File对象对应的文件或目录,若成功删除则返回true,否则false
- boolean createNewFile():当File对象对应的文件不存在时,该方法将新建一个此File对象指定的新文件,若创建成功则返回true,否则false
- String getName():返回File对象表示的文件或文件夹名称
- String getPath():返回File对象对应的路径
- String getAbsolutePath():返回File对象对应的绝对路径
- String getParent():返回File对象对应目录的父目录
- boolean canRead():判断File对象对应的文件或目录是否可选,若可选则返回true,反之则返回false
- boolean canWrite():判断File对象对应的文件或目录是否可写,若可选则返回true,反之则返回false
- boolean isFile():判断File对象是否是文件(非目录),若是则true,否则fasle
- boolean isDirectory():判断File对象是否是目录(非文件),若是则true,否则fasle
- boolean isAbsolute():判断File对象对应的文件或目录是否是绝对路径
- long lastModefied():返回1970年1月1日0时0分0秒到文件最后修改时间的毫秒值
- long length():返回文件内容的长度
- String[] list():列出指定目录的全部内容,只是列出名称
- File[] listFiles():返回一个包含了File对象所有的子文件和子目录的File数组
字符流文件复制
import jav.io.*;
public class Main{
public static void main(String args[]) throws Exception{
FileReader reader = new FileReader("src.txt");
BufferedReader br = new BUfferedReader(reader);
FileWriter writer = new FileWriter("dex.txt");
BufferedWriter bw = new BufferedWriter(writer);
String str;
while((str = br.readline()) != null){
bw.write(str);
bw.newLine();
}
br.close();
bw.close();
}
}
字节流复制(网上找的,了解大概过程就行了)
package iostream.FileOutputStream;
import java.io.*;
/**
* 使用FileInputStream和FileOutPutStream完成文件的拷贝
* 拷贝的过程应该是一边读一边写
* 使用以上字节流拷贝文件的时候,文件类型随意,万能的,什么样的文件都能拷贝
*/
public class FileOutPutStreamTest2 {
public static void main(String[] args) {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
//创建一个输入流对象
fileInputStream = new FileInputStream("/Users/yuuki/Downloads/loveletter.flv");
//创建一个输出流对象
fileOutputStream = new FileOutputStream("/Users/yuuki/Desktop/loveletter.flv");
//最核心的,一边读一边写,我们假使一次1M
byte[] bytes = new byte[1024 * 1024];
int readCount = 0;
while ((readCount = fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes,0,readCount);
}
//刷新,输出流最后要刷新
fileOutputStream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//分开try...catch,不要一起
//一起try...catch的时候,如果一个出现异常,可能会影响到另一个流的关闭
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileOutputStream != null) {
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
缓冲类
就是在内存中预留指定大小的存储空间用来对输入/输出(I/O)的数据作临时存储,这部分预留的内存空间就叫做缓冲区 缓冲区本质上是一个可以读写数据的内存块,可以理解成是一个数组,该对象提供了一组方法,可以更轻松地使用内存块
字符字节转换
-
字符串转字节
@Test public void TestDemo1(){ String str = "Hello, World!"; byte[] bytes = str.getBytes(); for(byte item : bytes){ System.out.println(item); } /** * 输出如下: * * 72 * 101 * 108 * 108 * 111 * 44 * 32 * 87 * 111 * 114 * 108 * 100 * 33 * **/ }
-
字节转字符串
@Test public void TestDemo1(){ String str = "Hello, World!"; byte[] bytes = str.getBytes(); String result = new String(bytes); System.out.println(result); /** * 输出如下: * Hello, World! * **/ }
第八章 多线程
Thread
继承Thread类创建多线程
public class Main{
public static void main(String args[]){
MyThread myThread = new MyThread();
myThread.start();
while(true){
System.out.println("Main方法在运行");
}
}
}
class MyThread extends Thread{
public void run(){
while(true){
System.out.println("MyThread类中的run()方法在执行");
}
}
}
Runnable
继承Runnable接口创建多线程
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();//创建MyThread实例对象
Thread thread = new Thread(myThread);//创建线程对象
thread.start();//开启线程
while(true){
System.out.println("main方法在运行");
}
}
}
class MyThread implements Runnable{
public void run(){//当调用start方法时,线程从此处开始执行
while(true){
System.out.println("MyThread类的run方法在执行");
}
}
}
异同
实现Runnable()接口相对于继承Thread类,有如下好处:
- 适合多个相同代码的线程去执行同一个资源的情况,把线程与程序代码、数据有效的分离,很好的体现了面向对象的设计思想
- 可以避免由于Java的单继承带来的局限性。
生命周期(状态及转换关系)
生命周期:
- 新建状态(New):处于新建状态,不能运行,仅仅是分配了内存
- 就绪状态(Runnable):当调用了start()方法后,该线程就处于就绪状态,只是具备了运行的条件,但是还需等待系统的调度
- 运行状态(Running):处于就绪状态的线程获得CPU使用权,并开始执行run()方法中的线程执行体,则处于运行状态
- 阻塞状态(Blocked):只有当引起阻塞的原因后,线程才可以进入就绪状态
- 死亡状态(Terminated):当线程调用stop()或run()方法正常执行完毕后,或者线程抛出一个未捕获的异常,错误,线程就进入死亡状态
死锁
看教材代码吧
优先级
优先级越高获得CPU执行机会越大
- static int MAX_PRIORITY:表示最高优先级,值为10
- static int MIN_PRIORITY:表示最低优先级,值为1
- static int NORM_PRIORITY:表示普通优先级,值为5
第九章 网络编程
TCP与UDP协议的区别,工作原理
UDP协议:无连接通信协议。发送数据时,数据的发送端和接收端不会建立逻辑连接。
UDP工作原理:当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在就会发出数据;同时接收端在收到数据时,也不会向发送端反馈受否收到数据。
UDP优点:消耗资源小,通信效率高,通常用于音频、视频和普通数据的传输,有面向无连接性。
TCP协议:面向连接的通信协议,即在传输数据前先在发送端和接收端建立逻辑连接,然后再传输数据,提供了两台计算机之间可靠无差错的数据传输。
TCP工作原理:由客户端向服务器端发送连接请求。每次连接要经历三次握手:第一次握手,客户端向服务端发出连接请求,等待服务器确认;第二次握手,服务端向客户端回送一个响应,通知客户端收到了连接请求;第三次握手,客户端再次向服务端发送确认信息,确认连接。
TCP协议的优点:保证传输数据安全性,下载文件必须使用TCP协议,有面向连接性。
编程实现通信
//客户端代码
package cn.edu.cwnu.网络编程;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
public class client {
public static void main(String[] args) throws Exception{
// new TCPClient().connect();
for (int i = 0; i < 3; i++) {//3为聊天语句的个数,可随意修改
TCPClient tcpClient = new TCPClient(i+1);
tcpClient.connect();
}
}
}
class TCPClient{
private static final int PORT = 7788;
private int i;
public TCPClient(){}
public TCPClient(int i){
this.i = i;
}
public void setI(int i){
this.i = i;
}
public int getI(){
return this.i;
}
public void connect() throws Exception{
Socket client = new Socket(InetAddress.getLocalHost(),PORT);
InputStream is = client.getInputStream();
System.out.print("客户端"+this.getI()+":");
byte[] buf = new byte[1024];
int len = is.read(buf);
System.out.println(new String(buf,0,len));
client.close();
}
}
//服务端代码
package cn.edu.cwnu.网络编程;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class ServerThread {
public static void main(String[] args) throws Exception{
new TCPServerThread().listen();
}
}
class TCPServerThread{
private static final int PORT = 7788;
public void listen() throws Exception{
ServerSocket serverSocket = new ServerSocket(PORT);
while(true){
final Socket client = serverSocket.accept();
new Thread(() -> {
OutputStream os;
try {
os = client.getOutputStream();
Scanner sc = new Scanner(System.in);
System.out.print("服务端:");
String str = sc.next();
os.write((str).getBytes());
Thread.sleep(5000);
os.close();
client.close();
}catch (Exception e){
e.printStackTrace();
}
}).start();
}
}
}
第十章 JDBC
JDBC含义
java提供的用于数据库编程的一套接口(自己总结的,也可以照着书上去写)
JDBC API
- Driver接口:所有JDBC驱动程序必须实现的接口
- DriverManager类:用于加载JDBC驱动并且创建与数据库的连接
- Connection接口:代表Java程序和数据库的连接,只有获得该连接对象后,才能访问数据库,并操作数据表
- Statement接口:用于执行静态SQL语句,并返回一个结果对象,可通过Connection实例的createStatement()方法获得
- PreparedStatement接口:封装了JDBC执行SQL语句的方法,可以完成Java程序执行SQL语句的操作
- ResultSet接口:用于保存JDBC执行查询时返回的结果集
实现JDBC 基本步骤
//1、加载并注册数据库驱动
DriverManager.registerDriver(Driver driver);
或者Class.forName("DriverName");
//2、通过DriverManager获取数据库连接
Connection conn = DriverManager.getConnection(String url,String user,String pwd);
//3、通过Connection对象获取Statement对象
Statement stmt = conn.createStatement();
//4、使用Statement执行SQL语句
ResultSet rs = stmt.executeQuery(sql);//sql指的是sql语句,如"select * from student"
//5、操作ResultSet结果集
//6、关闭连接,释放资源