视频列表
- 尚硅谷 Java 基础学习导读 20:27 尚硅谷
- 课程总结
- 第一个 Java 程序
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
// String args[] 与 String[] args 都可以执行,但推荐使用 String[] args,这样可以避免歧义和误读。
- Java 执行命令
- javac 命令: javac 后面跟着的是 Java 文件的文件名. 该命令用于将 .java 源文件编译成为 .class 字节码文件.
- java 命令: java 后面跟着的是 Java 文件中的类名. 该命令用于运行程序.
- 尚硅谷 Java语言概述 120:14 尚硅谷
- 课程总结
- Java 简介
Java 是由 Sun Microsystems 公司于1995年5月推出的 Java 面向对象程序设计语言和 Java 平台的总称. 后来被 Oracle(甲骨文) 公司收购, Java 也随之成为 Oracle 公司的产品. - Java的体系分类
- JavaSE (J2SE) (Java平台标准版)
- JavaEE (J2EE) (Java平台企业版)
- JavaME (J2ME) (Java平台微型版)
- Java 主要特性
- Java 语言是简单的
- Java 语言是面向对象的
- Java 语言是分布式的
- Java 语言是健壮的
- Java 语言的安全的
- Java 语言是体系结构中立的
- Java 语言是可移植的
- Java 语言是解释性的
- Java 语言是高性能的
- Java 语言是多线程的
- Java 语言是动态的
- Java 开发工具
- Linux 系统、Mac OS系统、Windows系统
- Java JDK 7、8 …
- vscode 编辑器或者其他编辑器
- IDE: Eclipse、 IntelliJ IDEA、 NetBeans等
- 尚硅谷 Java基本语法 278:31 尚硅谷
- 课程总结
- 基本语法:
- 大小写敏感
- 类名: 类名的首字母应该大写
- 方法名: 所有的方法名应该以小写字母开头, 后面的每个单词首字母大写
- 源文件名: 源文件名必须与类名相同.
- 主方法入口: 所有的 Java 程序均由 public static void main(String[] args) 方法开始执行.
- Java 标识符
- 所有的标识符都应该以字母、美元符、或者下划线开始
- 首字符之后可以是字母、美元符、下划线或者数字的任何字符组合
- 关键字不能用作标识符
- 标识符是大小写敏感的
- Java 修饰符
- 访问控制修饰符: default、public、protected、private
- 非访问控制修饰符: final、abstract、static、synchronized
- Java 变量
- 局部变量
- 类变量(静态变量)
- 成员变量(非静态变量)
- Java 关键字: 以下是部分关键字
- 尚硅谷 Eclipse的使用 89:09 尚硅谷
- 课程总结
- 常用快捷键
- Ctrl + S: 保存当前文件
- Ctrl + C: 复制
- Ctrl + V: 粘贴
- Ctrl + D: 删除当前行
- Ctrl + F: 查找/删除(当前编辑窗口)
- Ctrl + H: 全局搜索
- Ctrl + /: 注释当前行或多行代码
- Ctrl + Shift + C: 注释当前行或多行代码
- Ctrl + Shift + F: 格式化当前代码
- Ctrl + Shift + O: 缺少的 Import 语句被加入, 多余的 Import 语句被删除
- Ctrl + Shift + S: 保存所有文件
- Ctrl + Shift + X: 把当前选中的文本全部变成大写
- Ctrl + Shift + Y: 把当前选中的文本全部变成小写
- Alt + /: 代码智能提示
- Alt + Shift + R:重命名
- 常见概念和操作
- 项目(Project): Eclipse中所有的可以编译运行的资源必须放在项目中, 单独打开文件很多功能不可用. 项目表示了一系列相关的文件和设置(例如类路径,编译器级别, 发布路径等等的设置).
- 工作区(Workspace): 一个Eclipse可以有多个工作区, 每个工作区包含了多个项目, 以及所有其余的设置信息例如界面布局, 文字大小, 服务器定义等等.
- 导入、导出 Java 项目
- 优化导入列表: 代码中经常会导入无用的包和类, 通过菜单Source -> Organize Imports或者在编辑器的上下文菜单中选择菜单项Source -> Organize Imports, 或者按下快捷键Ctrl+Shift+O也可以来重新组织并去掉无用的类和包.
- 添加、修改、删除 JRE: 通过菜单Window -> Preferences, 然后选择Java > Installed JREs, 可以打开供在Eclipse编写程序所使用的JRE列表.
- 尚硅谷 数组 187:21 尚硅谷
- 课程总结
- 声明数组变量
- 首先必须声明数组变量, 才能在程序中使用数组.
dataType[] arrayRefVar; // 首选的方法
dataType arrayRefVar[]; // 效果相同,但不是首选方法
- 注意事项: 建议使用第一种声明方法声明数组变量. 是为了让 C/C++ 程序员可以快速理解 Java语言
- 创建数组
- Java 语言使用 new 操作符来创建数组, 语法如下:
arrayRefVar = new dataType[arraySize];
- 数组变量的声明, 和创建数组可以用同一条语句完成, 如下所示:
dataType[] arrayRefVar = new dataType[arraySize]; // 第一种方法
dataType[] arrayRefVar = {value0, value1, ..., valuek}; // 第二种方法
- 数组的元素是通过索引来访问的, 数组索引从 0 开始, 直到 array.length-1
- 处理数组: 数组的元素类型和数组的大小都是确定的, 所以当处理数组元素的时候, 我们通常使用基本循环或者 For-Each 循环.
- For-Each 循环(加强型循环, 不使用下标)
for(type element: array)
{
System.out.println(element);
}
- 数组作为函数的参数: 数组可以作为参数传递给方法
- 数组作为函数的返回值
- 多维数组
- Arrays 类
- 给数组赋值
- 对数组排序
- 比较数组
- 查找数组
- 个别方法如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vTAtAwJ4-1607591426378)(/Users/lipengyuan/Library/Application Support/typora-user-images/截屏2020-12-05 上午12.07.56.png)]
- 尚硅谷 面向对象 390:54 尚硅谷
- 课程总结
- 面向对象基本概念: 其本质是以建立模型体现出来的抽象思维过程和面向对象的方法, 是一种编程思维, 也是一种思考问题的方式.
- 类与对象:
- 类: 类是一种分类, 是一个类别, 一个模版, 他描述一类对象的行为和状态, 是一组具有相同特性(属性)与行为(方法)的事物集合.
// 类的定义格式
class 类名称{
属性名称;
返回值类型 方法名称(){}
}
- 对象: 是一个个性的产物, 是一个个体的特征, 是类的一个实例, 有状态和行为.
// 对象的定义格式
类名称 对象名称 = new 类名称() ;
- 封装性: 封装性是面向对象思想的三大特征之一, 封装就是隐藏实现细节, 今对外提供访问接口. 实现细节部分包装、隐藏起来的方法
- 属性的封装
- 方法的封装
- 类的封装
- 组建的封装
- 模块化封装
- 系统级封装
- 封装的好处
- 模块化
- 信息隐藏
- 代码重用
- 插件化易于调试
- 具有安全性
- 封装的缺点: 会影响执行效率
- 构造方法
- 无参构造方法: public Dog(){} // 如果一个类没有定义构造方法, 则默认使用无参构造方法, 如果有定义有参构造方法, 最好在定义一个无参构造方法.
- 带参构造方法
public Dog(String name){
this.name = name;
}
- 多参构造方法
public Dog(String name, int age){
this.name = name;
this.age = age;
}
- 构造方法名称与类名称相同, 没有返回值声明
- 构造方法用于初始化数据(属性)
- 每一个类中都会有一个默认的无参构造方法
- 如果类中有显示的构造方法, 那么默认构造方法将会无效
- 构造方法可以有很多, 但参数不一样, 成为构造方法的重载
- 在构造方法中调用另外一个构造方法, 使用 this, 该句代码必须放在第一行.
- this 关键字
- 调用类中的属性
- 调用类中的方法
- 调用类中的构造方法
- 注意事项
- this()不能使用在普通方法中, 只能写在构造方法中
- 必须是构造方法中的第一条语句
- 值传递和引用传递
- 对象的一对一关系
- Java 中对象的对应关系有很多, 比如说单向一对一、 双向一对一、 一对多、多对一、多对多等等, 其实现原理是相同的
- 可以理解为类的组合问题, 把对象当作另外一个的属性来操作, 使其产生对应关系.
- static 关键字
- 使用 static 关键字修饰一个属性: 声明为static的变量实质上就是全局变量
- 使用 static 关键字修饰一个方法: 无需本类的对象即可调用此方法
- 使用 static 关键字修饰一个类(内部类)
- 继承: 继承是面向对象三大特称之一, 是使用已存在的类的定义作为基础建立新类的技术, 新类的定义可以增加新的数据或新的功能, 也可以使用父类的功能, 但不能选择性的继承父类
- 被继承的类称为父类(超类)
- 继承父类的类称为子类(派生类)
- 子类拥有父类非private的属性和方法
- 子类可以拥有自己的属性和方法, 即子类可以对父类进行扩展
- 子类可以使用自己的方式实现父类的方法
- 对于构造器而言, 它只能够被调用, 而不能被继承, 可以通过使用 super() 进行调用
- 对于继承而言, 子类会默认调用父类的构造器, 但是如果没有默认的父类构造器, 子类必须定义指定的父类构造器(使用 super())
- 对于 Java的继承, 必须是单继承, 但是可以多重继承
[访问权限] class 子类名 extends 父类名{
类体定义;
}
- 方法的重写 : 在Java中, 子类可继承父类的方法, 为不需要重新编写新的方法. 但有时子类需要做一定修改, 就需要采用方法的重写, 亦称方法覆盖.
- 发生自子父类中, 方法重写的两个方法返回值、方法名、参数列表必须完全一致(子类重写父类的方法)
- 子类抛出的异常不能超过父类相应方法泡出的异常(子类异常不能大于父类异常)
- 子类方法的访问级别不可以低于父类相应方法的访问级别
- 父类中的方法若使用private、static、final任意修饰符修饰, 则方法不可被子类重写.
- super 关键字
- super 调用父类的属性
- super 调用父类的方法
- super 调用父类的构造方法
- final 关键字
- 使用 final 关键字声明一个常量
- 使用 final 关键字声明一个方法
- 使用 final 关键字声明一个类
- 在方法参数中使用 final, 在该方法内部不可以改变参数的值.
- 抽象类
- 很多具有相同特征和行为的对象可以抽象为一个类, 很多具有相同特征和行为的类可以抽象为一个抽象类
- 使用 abstract 关键字声明的类为抽象类
abstract class Animal{
public abstract void move();
}
abstract class Person extends Animal{
private String name;
//...
public abstract void eat();//抽象方法
}
- 抽象类的规则
- 抽象类可以没有抽象方法, 有抽象方法的类必须是抽象类
- 非抽象类继承抽象类必须实现所有抽象方法
- 抽象类可以继承抽象类, 可以不实现父类抽象方法
- 抽象类可以有方法实现和属性
- 抽象类不可以被实例化
- 抽象类不可以被声明为 final
- 抽象类可以有构造方法
- 接口
// 接口的定义格式:
interface 接口名称{
全局常量 ;
抽象方法 ;
}
- 接口的使用规则
- 定义一个接口, 使用 interface 关键字
- 在一个接口中, 只可以定义常量、抽象方法
- 接口可以继承多个接口
- 一个具体类实现接口使用 implements 关键字
- 一个类可以实现多个接口
- 抽象类实现接口可以不实现接口的方法
- 在接口中定义的方法没有声明访问修饰符, 默认为 public
- 接口中不能有构造方法
- 接口不可以被实例化
- 多态性: 多态指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定, 而是在程序运行期间才确定, 即一个引用变量到底指向哪个类的实例化对象, 该引用变量发出的方法调用到底是哪个类中实现的方法, 必须在程序运行期间才可以决定. 即不修改程序代码就可以改变程序运行时所制定的具体代码, 就可以让程序选择多个运行状态, 这就是多态性
- 方法的重载和重写
- 对象的多态性: 是从继承关系中的多个类而来的
- 向上转型: 将子类实例转为父类引用
- 向下转型: 将父类实例转为子类实例
- instanceof 关键字: 用来检查对象是否为指定的类型, 通常在父类引用强制转换为子类引用时使用, 以避免发生类型转换一异常
// 语法格式如下:
对象 instanceof 类型--返回boolean类型值
// 示例:
if(homeChicken instanceof Chicken){
//...
}
- 内部类: 在一个类中定义的类
- 成员内部类: 内部类对象依赖外部类对象而存在, 即在创建一个普通内部类对象时首先需要创建其外部类对象
- 内部类对象可以方法问外部类对象中所有访问权限的字段, 此外, 外部类对象也可以通过内部类的对象引用来访问内部类中定义的所有方法权限的字段.
// 成员内部类格式如下:
class Outer {
class Inner{}
}
- 局部内部类: 内部类可以作为一个类的成员外, 还可以把类放在方法内定义
- 局部内部类只能在定义该内部类的方法内实例化, 不可以再次方法外对其实例化
- 局部内部类对象不能使用该内部类所在方法的非 final 局部变量
class Outer {
public void doSomething(){
class Inner{
public void seeOuter(){}
}
}
}
- 静态内部类: 在一个类内部定义一个静态内部类. 静态的含义是该内部类可以向其他静态成员一样, 没有外部类对象时, 也可以访问他. 静态嵌套类仅能访问外部类的静态成员和方法.静态内部类中也无法访问外部类的非静态成员
class Outer{
static class Inner{}
}
class Test {
public static void main(String[] args){
Outer.Inner n = new Outer.Inner();
}
}
- 匿名内部类: 没有名字的内部类
- 继承式的匿名内部类
- 接口式的匿名内部类
- 参数式的匿名内部类
- 不能有构造方法, 只能有一个实例
- 不能定义任何静态方法、静态成员
- 不能是 public、protected、private、static
- 一定是在 new 后面, 用来隐含实现一个接口或继承一个类
- 匿名内部类是局部的, 所以局部内部类的所有限制都对其有效
- 尚硅谷 异常处理 120:16 尚硅谷
- 课程总结
- Java 异常处理
- 异常发生的原因
- 用户输入了非法数据
- 要打开的文件不存在
- 网络通信是连接中断, 或者 JVM 内存溢出
- 需要掌握的常见异常
- 检查性异常
- 运行时异常
- 错误
- Exception 类的层次
- 所有的异常类都是从 java.lang.Exception 类继承的子类
- Exception 类是 Throwable 类的子类
- 异常类有两个主要的子类: IOException 类和 RuntimeException 类
- Java 内置异常类: 标准运行时异常类的子类是最常见的异常类
- 异常方法
- 捕获异常
- 使用 try 和 catch 关键字可以捕获异常. try/catch 代码块放在异常可能发生的地方.
- try/catch 代码块中的代码称为保护代码
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
- Catch 语句包含要捕获异常类型的声明. 当保护代码块中发生一个异常时, try 后面的catch块就会被检查.
- 多重捕获块: 一个 try 代码块后面跟随多个 catch 代码块的情况就叫做多重捕获
try{
// 程序代码
}catch(异常类型1 异常的变量名1){
// 程序代码
}catch(异常类型2 异常的变量名2){
// 程序代码
}catch(异常类型3 异常的变量名3){
// 程序代码
}
- throws/throw 关键字: 如果一个方法没有捕获到一个检查性异常, 那么该方法必须使用 throws 关键字来声明. throws 关键字放在方法签名的尾部.
import java.io.*;
public class className
{
public void deposit(double amount) throws RemoteException
{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
- Finally 关键字: finally 关键字用来创建在 try 代码块后面执行的代码块. 无论是否发生异常, finally 代码块中的代码总会被执行.
- catch 不能独立与 try 存在
- 在 try/catch 后面添加 finally 块并非强制性要求
- try 代码后不能既没 catch 块也没 finally 块
- try、 catch、 finally 块之间不能添加任何代码.
- 声明自定义异常
- 所有异常都必须是 Throwable 的子类
- 如果希望写一个检查性异常类, 那么需要继承 Exception 类
- 如果希望写一个运行时异常类, 那么需要继承 RuntimeException 类
class MyException extends Exception{
}
- 通用异常
- JVM(Java虚拟机)异常: 由 JVM 抛出的异常或错误。例如:NullPointerException 类,ArrayIndexOutOfBoundsException 类,ClassCastException 类。
- 程序级异常: 由程序或者API程序抛出的异常。例如 IllegalArgumentException 类,IllegalStateException 类。
- 尚硅谷 多线程 160:16 尚硅谷
- 课程总结
- Java 多线程编程: 一条线程指的是进程中一个单一顺序的控制流, 一个进程中可以并发多个线程, 每条线程并行执行不同的任务. 多线程是多任务的一种特别的形式, 但多线程使用了更小的资源开销.
- 一个线程的生命周期: 线程是一个动态执行的过程, 他也有一个从产生到死亡的过程.
1. 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个多线程对象后, 该线程对象就处于新建状态. 他保持这个状态知道程序 start() 这个线程.
- 就绪状态: 当线程对象调用了 start() 方法之后, 该线程就进入了就绪状态. 就绪状态的线程处于就绪队列中, 要等待 JVM 里线程调度器的调度.
3. 运行状态: 如果就绪状态的线程获取 CPU 资源, 就可以执行 run(), 此时线程便处于运行状态. 处于运行状态的线程最为复杂, 它可以变为阻塞状态、就绪状态和死亡状态.
4. 阻塞状态: 如果一个线程执行了 sleep(睡眠)、suspend(挂起)等方法, 失去所占有资源之后, 该线程就从运行状态进入阻塞状态. 在睡眠时间已到或获得设备资源后可以重新进入就绪状态.
- 等待阻塞: 运行状态中的线程执行 wait() 方法, 使线程进入到等待阻塞状态
- 同步阻塞: 线程在获取 synchronize 同步锁失败(因为同步锁被其他线程占用)
- 其他阻塞: 通过调用线程的sleep()或join()发出了 I/O 请求时, 线程就会进入到阻塞状态. 当sleep()状态超时, join()等待线程终止或超时, 或者 I/O 处理完毕, 线程重新进入就绪状态
- 死亡状态: 一个运行状态的线程完成任务或者其他终止条件发生时, 该线程就切换到终止状态
- 线程的优先级: 每一个 Java 线程都有一个优先级, 这样有助于操作系统确定线程的调度顺序
- 创建一个线程
- 通过实现 Runnable 接口
- 通过继承 Thread 类本身
- 通过 Callable 和 Future 创建线程
- 通过实现 Runnable 接口来创建线程
- 为了实现 Runnable, 一个类只需要执行一个方法调用 run()
public void run()
- 我们可以重写该方法, 重要的是run()可以调用其他方法, 使用其他类, 并声明变量, 就像主线程一样. 在创建一个实现 Runnable 接口的类之后, 可以在类中实例化一个线程对象
Thread(Runnable threadOb,String threadName);
- 新线程创建之后, 你调用他的 start() 方法, 他才会运行
- 通过继承 Thread 来创建线程
- 继承 Thread 类, 然后创建一个该类的实例. 并且必须重写 run() 方法, 该方法是新线程的入口点, 他也必须调用 start() 方法才能执行
- Thread 方法
- 判断线程是否处于活动状态
- 通过 Callable 和 Future 创建线程
- 创建 Callable 接口的实现类, 并实现 call() 方法, 该 call() 方法将作为线程执行体, 并且有返回值
- 创建 Callable 实现类的实例, 使用 FutureTask 类来包装 Callable 对象, 该 FutureTask 对象封装了该 Callable 对象的call()方法的返回值
- 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程
- 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值
- 尚硅谷 集合 198:04 尚硅谷
- 课程总结
- Java 集合框架
- 该框架必须是高性能的. 基本集合(动态数组、链表、树、哈希表)的实现也必须是高效的
- 该框架允许不同类型的集合, 以类似的方式工作, 具有高度的互操作性
- 对一个集合的扩展和适应必须是简单的
- 包含内容
- 接口: 代表集合的抽象数据类型
- 实现(类): 是集合接口的具体实现
- 算法: 实现集合接口的对象里的方法执行的一些有用的计算
- 集合接口
- Set 与 List 的区别
- Set 接口实例存储的是无序的, 不重复的数据. List 接口实例存储的是有序的, 可以重复的元素.
- Set 检索效率低下, 删除和插入效率高, 插入和删除不会引起元素位置改变
- List 和数组类似, 可以动态增长, 根据实际存储的数据的长度自动增长List的长度. 查找元素效率高, 插入删除效率低, 因为会引起其他元素位置的改变
- 集合实现类(集合类)
- 集合算法: 集合框架定义了几种算法, 可用于集合和映射. 这些算法被定义为集合类的静态方法
- 如何使用迭代器: 迭代器, 是你可以通过循环来得到或删除集合的元素. ListIterator 继承了 Iterator, 以允许双向遍历列表和修改元素
- 如何使用比较器
- 尚硅谷 泛型与File 94:33 尚硅谷
- 课程总结
- Java 泛型: 提供了编译时类型安全监测机制, 该机制允许程序员在编译时检测到非法的类型. 泛型的本质上是参数化类型, 也就是说所操作的数据类型被指定为一个参数
- 泛型方法
- 所有的泛型方法声明都有一个类型参数声明部分(由尖括号分隔), 该类型参数声明部分在方法返回类型之前.
- 每一个类型参数声明部分包含一个或多个类型参数, 参数间使用逗号隔开. 一个泛型参数, 也被称为一个类型变量, 是用来制定一个泛型类型名称的标识符
- 类型参数能被用来声明返回值类型, 并且可以作为泛型方法得到的实际参数类型的占位符
- 泛型方法体的声明和其他方法一样. 注意类型参数只能代表引用型类型, 不能是原始类型.
- 泛型类
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("菜鸟教程"));
System.out.printf("整型值为 :%d\n\n", integerBox.get());
System.out.printf("字符串为 :%s\n", stringBox.get());
}
}
- 类型通配符
- 类型通配符一般是使用 ? 代替具体的类型参数. 例如 List<?>在逻辑上是 List、List等所有.
- 尚硅谷 IO流 124:19 尚硅谷
- 课程总结
- Java 流(Steam)、文件(File)和IO
- 读取控制台输入
- Java 的控制台输入是有 System.in 完成
- 为了获取一个绑定到控制台的字符流, 你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流
BufferedReader br = new BufferedReader(new
InputStreamReader(System.in));
- BUfferReader 对象创建后, 我们便可以使用 read()方法从控制台读取一个字符, 或者用readLine()方法读取一个字符串.
- 从控制台读取多字符输入
- 从控制台读取字符串
- 从标准输入读取一个字符串需要使用 BufferReader 的 readLine()方法
String readLine( ) throws IOException
- 控制台输出
- 控制台输出由 print() 和 println()完成, 这些方法都由类 PrintStream 定义, System.out是该类对象的一个引用
- PrintStream 继承了 OutputStream 类, 并且实现了方法 write()
- 读写文件
- FileInputStream: 该流用于从文件读取数据, 他的对象可以用关键字 new 创建
- FileOutputStream: 该类用来创建一个文件并向文件中写数据
- 文件和 I/O
- 尚硅谷 网络编程 121:48 尚硅谷
- 课程总结
- Java 网络编程: 网络编程是指编写运行在多个设备(计算机)的程序, 这些设备都通过网络连接起来.
- java.net 包中提供了两种常见的网络协议的支持
- TCP: TCP 是传输控制协议的缩写,它保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP
- UDP: UDP 是用户数据报协议的缩写,一个无连接的协议。提供了应用程序之间要发送的数据的数据包
- Socket 编程:
- 套接字使用 TCP 提供了两台计算机之间的通信机制. 客户端程序创建一个套接字, 并尝试链接服务器的套接字. 当链接建立时, 服务器会创建一个 Socket 对象. 客户端和服务器现在可以对 Socket 对象的写入和读取来进行通信
- java.net.Socket 类代表一个套接字, 并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端, 并与他们建立连接的机制
- 在两台计算机之间使用套接字建立TCP连接时会出现
- 服务器实例化一个 ServerSocket 对象, 表示通过服务器上的端口通信
- 服务器调用 ServerSocket 类的 accept() 方法, 该方法将一直等待, 直到客户端连接到服务器上给定的端口
- 服务器正在等待时, 一个客户端实例化一个 Socket 对象, 指定服务器名称和端口号来请求连接
- Socket 类的构造函数试图将客户端连接到指定的服务器和端口号, 如果通信被建立, 则客户端创建一个 Socket 对象能够与服务器进行通信
- 在服务器端, accept()方法返回服务器上一个新的 socket 引用, 该 socket 连接到客户端的 socket
- ServerSocket 类的方法
- Socket 类的方法
- InetAddress 类的方法
- Socket 客户端实例
// 文件名 GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("连接到主机:" + serverName + " ,端口号:" + port);
Socket client = new Socket(serverName, port);
System.out.println("远程主机地址:" + client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out = new DataOutputStream(outToServer);
out.writeUTF("Hello from " + client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in = new DataInputStream(inFromServer);
System.out.println("服务器响应: " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
- Socket 服务端实例
// 文件名 GreetingServer.java
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread
{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run()
{
while(true)
{
try
{
System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
DataInputStream in = new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = Integer.parseInt(args[0]);
try
{
Thread t = new GreetingServer(port);
t.run();
}catch(IOException e)
{
e.printStackTrace();
}
}
}