Java学习笔记(黑马程序员)
java直接看ppt吧
跟C++很多相似,记载一些不一样的东西
JDK与JRE
SDK是Software Development Kit 一般指软件开发包,可以包括函数库、编译程序等。
JDK( Java Development Kit )是面向Java开发人员使用的SDK,它提供了Java的开发环境和运行时环境JRE(Java Runtime Enviroment) 。
JRE是面向Java程序的使用者,而不是开发者
如同 Win32应用程序需要操作系统帮我们运行一样,Java程序需要JRE才能运行。
jvm.dll无法单独工作,当jvm.dll启动后,会使用explicit的方法(就是使用Win32 API之中的LoadLibrary()与GetProcAddress()来载入辅助用的动态链接库),而这些辅助用的动态链接库(.dll)都必须位于jvm.dll所在目录的父目录之中。
一.java简介
这部分大多和考试无关所所以没有做什么笔记,大多是理解性的概念。
Java程序都是以类来组织,一个文件中可以有多个类。
每个类编译完成后会生成各自的字节码文件。
类名前可加public也可不加,加了以后保存的文件名必须要跟这个类的名字相同。
一个源文件中只能含有一个标记为public的类。
main函数通常应放在public类中。
二.Java语言基础
1.String Pool
JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存空间,这就是我们今天要讨论的核心,即字符串池(String Pool)。字符串池由String类私有的维护。
采用new关键字新建一个字符串对象时,JVM首先在字符串池中查找有没有”aaa”这个字符串对象,如果有,则不在池中再去创建”aaa”这个对象了,直接在堆中创建一个”aaa”字符串对象,然后将堆中的这个”aaa”对象的地址返回赋给引用str3,这样,str3就指向了堆中创建的这个”aaa”字符串对象;如果没有,则首先在字符串池中创建一个”aaa”字符串对象,然后再在堆中创建一个”aaa”字符串对象,然后将堆中这个”aaa”字符串对象的地址返回赋给str3引用,这样,str3指向了堆中创建的这个”aaa”字符串对象。
String Pool的存在是基于String类对象定义就不可改变的基础之上
java中“ == ”实际比较的是等式俩边对象的地址,这样就能理解String a =“aaa”,和String b =new String (“aaa”)为何a,b不等了;
2.标识符与关键字
Java标识符是以字母、下划线()或美元符号($)开头;随后跟随字母、下划线()、美元符号($)或数字。标识符是大小写区别对待的。标识符未规定最大长度。下列标识符是有效的:identifier、userName、User_name、_sys_varl、$change。标识符不能是关键字,例如,this是一个关键字不能作为标识符。
3.数据类型
多了一个byte型,占8个bit,取值-128到127
在java中字符表现形式位单个字符加上一对单引号修饰;
boolean有两个文字值,即true和false(小写)。
注意:数字值不能自动转换为boolean 。
1 | 例如: |
有关char类的一些方法
已知 char ch=’a’;Character.isLetter(ch) – ch
是否是字母Character.isDigit(ch) – ch是否是数字
Character.isLetterOrDigit(ch) – ch是否是字母或数字
Character.isWhitespace(ch) – ch是否是空格
Character.isLowerCase(ch) – ch是否是小写字母
Character.isUpperCase(ch) – ch是否是大写字母
4.数据输出格式的控制
方法1:String.format(“格式串”,数值数据)
方法2:System.out.printf(“格式串”,数值数据)
1 | 示例: |
5.变量初始化
实例变量在分配存储单元的同时被下列值初始化:
byte、short、int:0
long:0L
float:0.0f
double:0.0d
char:’\u0000’ (即Null)
boolean:false
所有引用类型: Null
6.String类型
String不是基(原始)类型,而是一个类(class),它被用来表示字符序列(字符串)。字符本身符合Unicode标准。
与C和C++不同,String不用 ‘\0’ 作为结束。
基本用法:
直接赋值:String s1=”Hello”, s2=” Java”;
或者new一个String:String s1=new String(“Hello”);
字符串连接操作:String s3=s1+s2; //字符串连接 s3=”Hello Java”
int i=10; String str=”i=”+ i; //str的值为”i=10”
7.JVM的内存分区
3个区:堆(heap)、栈(stack)和方法区(method)
8.字符串 数值的转换
字符串→数值
方法1: √ parse方法常用
int i = Integer.parseInt(“123”);
double d = Double.parseDouble(“1.23”);
方法2:
int i =Integer.valueOf(“123”).intValue();
注意:字符串转换成数值时对数据格式要求严格i
nt i = Integer.parseInt(“123.4”); ×
int I = Integer.valueOf(“123.4”).intValue(); ×
数值→字符串
方法1:
String s=String.valueOf(value);
其中value为任一种数字类型。
方法2:
String s = Integer.toString(123);
方法3:
最直接 String s = “” + value;
其中value为任意一种数字类型。
9.类型转换
向上转型是被允许的,向低位转型会造成数据溢出;
对 + 运算符来说,当两个操作数是原始数据类型时,其结果至少有一个int,并且有一个通过提升操作数到结果类型、或通过提升结果至一个较宽类型操作数而计算的值,这可能会导致溢出或精度丢失。
例如:
short a,b,ca=1;
b=2;
c= a+b;
上述程序会因为在操作short之前提升每个short至int而出错。
然而,如果c被声明为一个int,或按如下操作进行类型转换:
c = (short)(a+b);
上述代码将会成功通过。
10.instanceof(必考)
作用:测试该运算符左边的对象是否是它右边的类(或接口)的实例,返回boolean类型的数据。
例如:Integer d = 123; boolean isInt = d instanceof Integer; //true
boolean isObj = d instanceof Object; //true
说明: Object 是类层次结构的根类,每个类都使用 Object 作为超类。Instanceof常用于Java反射时。
11.包装类

java语言不把基本数据类型看作对象。8个基本数据类型都有相应的包装类。
包装类都有自己的属性和方法
可以通过将被包裹的值传递到合适的构造函数中来构造包装类对象
int a = 100;
Integer i = new Integer(a); //构造包装类对象 (直接 i=a; 也可)
可以通过intValue()方法将包装类变成基本类型。
例如:int theInt = new Integer(200).intValue();
12.控制台输入
1 | import java.util.Scanner; //导入java包 |
int score=new Scanner(System.in).Double(); //连在一起写
相应的有:
nextInt()、nextByte()、nextFloat()、nextLong()
nextBoolean():获取boolean数据,如输入true或false
nextLine():获取字符串数据
注意获取控制台输入数据的流程
13.数学类
java.lang.Math类主要包括下列方法和两个常数 :
double abs(double d):返回d的绝对值。
double min(double d1, double d2) :返回d1与d2中的小者。
double max(double d1, double d2) :返回d1与d2中的大者。
double sqrt(double d):返回d的平方根。
double pow(double d1, double d2):返回d1的d2次幂。
double random():返回 [ 0,1) 的随机数。
两个常数:
PI:圆周率,double。
E:自然对数的底,double。
14.StringBuffer类
在Java中有3个类来负责字符的操作:
Character 是进行单个字符操作的。
String 对一串字符进行操作。不可变类。
StringBuffer 也是对一串字符进行操作,但是可变类。
StringBuffer对象只能通过构造函数来建立:
StringBuffer构造函数StringBuffer():创建一个空的StringBuffer。
StringBuffer(int capacity) :创建一个空的StringBuffer,容量(总长度)是capacity。
StringBuffer(String str) :以str为初始值构造一个StringBuffer。
1 | StringBuffer s = new StringBuffer(); |
StringBuffer是一个可变对象,当对它进行修改的时候不会像String那样重新建立对象
在实际应用中,经常会遇到对字符串进行动态修改。这时候,String类的功能受到限制,而StringBuffer类可以完成字符串的动态添加、插入和替换等操作。
原因:
变量使用final修饰后,放在堆(不是栈)中,其值不可更改。String类使用final修饰,因此,String对象在定义后,不可修改。而StringBuffer则不同,所以能够修改。


15.Java数组(程序阅读、程序填空)
一维数组的声明:
int a[ ]; //方便学过C的人,但不是推荐用法
int a[5]; ×
int[ ] a; //中括号放在类型后,推荐用法
注意:
int[ ] s1, s2; // s1,s2都是整型数组
int s1[ ], s2; // s1是整型数组,s2是整型变量
一维数组的创建:
数组声明不能创建对象本身,而是创建的一个引用,该引用可被用来引用数组。
数组元素使用的实际存储器可由new语句动态分配:
数组名 = new 数据类型[数组元素个数]
例如:
int[ ] a; a = new int[5];
或:int[ ] a = new int[5];
或:int n=5; int[ ] a = new int[n] ; √
此时数组元素默认值均为0
一维数组的初始化
Java语言允许使用下列形式快速初始化数组:
int[ ] a={ 1,2,3,4,5 }; √ 常用
int[ ] a=new int[ ]{ 1,2,3,4,5 }; √ 注意这种情况数组初始化不能指定元素的个数,即方括号内不能有数字;
一维数组遍历的新方法
for-each循环 (Java5.0后)
1 | for ( type varname : obj ) { |
type:数据类型;
varname:元素变量;
obj:需要遍历的对象,如数组、集合等。
二维数组的创建
int[ ][ ] a = new int [3] [3];
或者:
int[ ] [ ] a = new int [3] [ ]; //先指定第一维
a[0] = new int[3]; //再第二维分配
a[1] = new int[3];
a[2] = new int[3];
第二维可不相等

a.length 行数;
a[i].length 每行长度,列数;
foreach输出二维数组
1 | 示例: |
16.Java异常(程序设计题)
1)关键字
java异常处理涉及五个关键字: try、catch、finally throw、throws。
1 | 用法: |
通用异常类型的处理catch (Exception e)
一个try块可能有多个catch块,每一catch块处理不同的异常。
匹配原则:由上到下只匹配其中一个异常类,而不会再执行别的catch块。
finally语句:
定义一个总是要执行的代码块,而不考虑异常是否被捕获。
举一个例子:
1 | public class test { |
运行结果:
数据转换出错了!
一定要执行的块
k=0
注意:
try、catch、finally三个语句块均不能单独使用,三者可以组成 try…catch…finally、try…catch、try…finally三种结构,catch语句可以有一个或多个,finally语句最多一个。
try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。(如前例的 int k 变量)

2)Java异常分类
Java异常类分为两大类,错误类Error和异常类Exception。 (见后图)
java.lang.Throwable作为所有异常的超类。


3)throws和throw
由于有时默认的错误信息通常晦涩难懂,很难解释程序在何处出了何种问题。
为了使程序更加健壮,对于有些异常是当前层不能解决的,则可上报给上层(抛出异常),由上层来处理。
所以Java有throws和throw:
throws关键字:出现在方法的声明中,表示该方法可能会抛出的异常,允许throws后面跟着多个异常类型。
throws用法:方法声明 [throws <异常类>] { 方法实现… } 其中:异常类可以声明多个,用逗号分割。
throw关键字:throw出现在方法体中,用于抛出一个具体的异常对象。
throw用法:if(异常条件) throw <异常对象> ; 或
try{…} catch { throw <异常对象>; }
注意:throws可以单独使用,但throw不能。 throw要么和try-catch-finally语句配套使用,要么与throws配套使用。
例子:


4)自定义异常类
用户自定义异常类是通过扩展Exception类来创建的。这种异常类可以包含一个“普通”类所包含的任何东西。
1 | class MyException1 extends Exception { //自定义异常类 |
运行结果:抛出自定义异常:输入值小于100
处理问题的例子
1 | class MyException1 extends Exception { |
三.Java面向对象的程序设计
1.类的声明
{
属性声明:
方法声明:
2.包package
多数软件系统是庞大的,为了方便管理,通常要将类组织成包。
在包中可以存放类,也可以存放子包,从而形成具有层次结构的包。
包可以根据需要任意组织,通常,要按照类的用途、含义来组织包。




3.Java多态
java单继承性:(extends )
Java只支持单继承(一个类只能有一个父类),不支持多继承。(C++支持多继承)
重载的条件 :
方法名必须相同
方法的参数类型、个数、顺序至少有一项不相同。
方法覆盖:
通过继承可以获得父类的属性和方法。在此基础上,不仅可在子类中增加属性和方法,而且还可修改父类方法。
如果在新类中定义一个方法,其名称、参数表及返回类型正好与父类中方法的名称、参数表及返回类型相匹配,那么,新方法被称做旧方法的覆盖方法。
覆盖方法的规则 :
子类方法的名称、参数表、返回类型必须与所覆盖方法的名称、参数表、返回类型相同
子类的方法不能缩小所覆盖方法的访问权限(覆盖方法不能比它所覆盖的方法访问性差)
子类方法不能抛出比所覆盖方法更多的异常
关键字super
关键字super可被用来引用该类中的直接父类,通常被用来引用直接父类的成员变量或方法(前提成员是public类型)。
俩个例子:
super.getDetails(); 用super调用直接父类的方法
super(s); 调用直接父类的构造函数
当使用super或this时,它们必须被放在构造函数的第一行。显然,两者不能被放在一个单独行中。
4.抽象类
Java类中可以定义一些不含方法体的方法,它的方法体的实现将交给该类的子类根据自己的情况去实现,这样的方法就是抽象方法,包含抽象方法的类就叫抽象类。
例子:
1 | abstract class A { //抽象类 |
注意:
抽象类不能用final来修饰
abstract不能与private、static、final并列修饰同一个方法。(因为不能被继承或覆盖)
抽象类特点
含有抽象方法的类必须被声明为抽象类。
★abstract方法只需声明,而不需实现。抽象类可以有构造方法,但构造方法不能被声明为抽象。
★抽象类不能被实例化,即不能用new去产生对象,但可声明对象。
★ 抽象类的子类必须覆盖所有的抽象方法后才能被实例化,否则这个子类还是个抽象类。
5.接口interface
1.如果一个抽象类中的所有方法都是抽象的,可将这个类使用关键字interface(代替class)定义为接口。(接口是一种特殊的抽象类)
2.接口是抽象方法和常量值的定义的集合,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现。
3.接口的所有方法通常由子类全部实现,不同子类的实现可以具有不同的功能。
4.Java只支持单继承,不支持多继承。Java使用接口来克服单继承缺陷,一个类可以实现多个接口,从而间接地实现多继承。
把定义一个类的class关键字改为interface ,即定义接口。
接口中只能有抽象方法,即没有方法体的方法,如 public void method();
接口中的成员,只能是final声明的,即常量,如final int PI=3.14;
接口中的抽象方法,只能够是public或者没有修饰符的方法。如果没有修饰符修饰,默认是public方法。
特点:
java接口不能有构造方法(构造器),不能被实例化。(抽象类可以有构造函数)
Java接口中的成员常量默认是用public static final标识的(可省略),都是全局静态常量,必须被显示初始化。
Java接口中的方法默认都是public abstract类型的(可省略),没有方法体。
接口中不能包含静态方法(1.8版本后允许,但要给出方法体)。
一个接口不能实现(implements)另一个接口,但可继承(extends)多个其它的接口。
例子:
1 | interface b{ … } |
一个类在继承一个父类的同时,可实现一个或多个接口,但extends关键字必须位于implements关键字之前。
例如:public class A extends B implements C, D {…}
不允许创建接口的实例(实例化),但允许定义接口类型的引用变量,该引用变量引用实现了这个接口的类的实例。
恢复子类对象的功能
在接收父类的一个引用时,可以用类型转换该引用的办法来恢复子类对象的全部功能。
转换前可使用instanceof运算符判定该对象是否是你所要的子类。
1 | Employee e = new Manager(); |
如果不用强制类型转换,那么引用 e.department 的尝试就会失败,因为编译器不能将被称做 department 的成员定位在Employee类中。
如果不用instanceof做测试,就会有类型转换失败的危险。
6.使用关键字static
通常情况下,类成员必须通过类的对象来访问,但是可以创建这样的成员,它的使用完全独立于该类的任何对象。(即类成员能够被类自己使用,而不必引用特定的实例)
如果一个成员被声明为static,它就能够在它的类的任何对象创建之前被访问,而不必引用任何对象。
static关键字用来声明成员属于类,而不是属于类的实例。
静态方法有以下几条限制:
它仅能调用其他的static 方法。
它只能访问static数据。
它不能以任何方式引用this 或super
如果static变量没有被标记成private,也可以不需要类的实例,而通过类名指向它。即“类名.静态变量”。
静态代码块
static { 语句块 }
静态块代码只会初始化一次,且在类被第一次装载时。
类中不同的静态块按它们在类中出现的顺序被执行。
7.使用关键字final
final类:
如果这个类不需要有子类,类的实现细节不允许改变,并且确信这个类不会载被扩展,那么就设计为final类。
final类不能被继承。因此final类的成员方法没有机会被覆盖。
final方法:
被标记为final的方法可以被继承,但不能被覆盖。
使用final方法的原因有二:
把方法锁定,防止任何继承类修改它的意义和实现。
高效。编译器在遇到调用final方法时候会转入内嵌机制,大大提高执行效率。
实际上被标记为static或private的方法被自动final。
final变量:
如果变量被标记为final,其结果是使它成为常数。
注意:final变量定义的时候,可先声明,不给初值,(称为final空白变量)。但空白final在使用之前必须被初始化。
final参数 :
当函数参数为final类型时,只可以读取使用该参数,但是无法改变该参数的值。
8.内部类+匿名类(对象)
Outer2.Inner inner = outer.new Inner( );
内部类特点
内部类只在定义他们的代码段内可见。
内部类可以被定义在方法中。如果方法中的变量被标记为final,那么,就可以被内部类中的方法访问。
内部类可以使用所嵌套类的类和实例变量以及所嵌套的块中的本地变量。(内部类可以使用外部类的所有成员,包括私有成员)
内部类可以被定义为abstract.
可变参数
在Java类方法中,可以在类型名与参数之间使用“…”来表示可变参数。可变参数即为不确定个数的参数,在Java内部使用数组来处理。在类方法为使用可变参数的示例代码如下:
1 | public class VarableParameter { |
四.Java进程与多线程

进程是正在执行的程序。
线程是进程中一个单一的顺序控制流程。
一个或更多的线程构成了一个进程。线程是进程中的一个实体,是能被OS独立调度和分派的基本单位。

创建多线程
1.线程类实现Runnable接口,并重写run()方法
1 | class HelloThread implements Runnable { |
Thread类构造函数用Runnable的一个实例来创建一个线程
2.创建Thread类的子类重写run方法

线程同步
使用关键字synchronized
synchronized修饰代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
synchronized修饰某个方法时,表明该方法只能有一个线程执行,其他线程处于等待状态。
synchronized修饰某个类的声明时,表明这类中的所有方法都是synchronized的。
例子:
1 | class HelloThread implements Runnable { |
注意用法;
示例 – 同步方法
1 | class HelloThread1 implements Runnable { |
Join()的同步
让“主线程”等待“子线程”结束之后才能继续运行

线程协作
简单的说就是:
如果条件不满足,则等待。当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。

**wait()、notify()、notifyAll()**:
wait():释放已持有的锁,进入wait队伍。
notify():唤醒wait队列中的第一个线程,并将该线程移入互斥锁申请队列。
notifyAll():唤醒wait队列中的所有的线程,并将这些线程移入互斥锁申请队列。
如果线程对一个指定的对象x发出一个wait()调用,该线程会暂停执行,直到另一个线程对同一个指定的对象x发出一个notify ()调用。
注:wait()、notify()、notifyAll()三种方法只能出现在synchronized作用的范围内。
线程协作示例“
1 | public synchronized void putball(Object ball) { //往篮子里放球 |
线程的生命周期

异步任务处理
通常方法调用分为同步调用和异步调用两类。打电话是一个典型的同步调用,发起者需要等待接收者,接通电话后,通信才开始。
相对同步而言,异步可以大大提高线程效率。现在的CPU 都是多核的,使用异步处理可以同时做多项工作。广播就是一个典型的异步例子,发起者不关心接收者的状态,不需要等待接收者的返回信息。
五.Java集合框架与泛型
要熟悉它们的基本用法
集合概述:
通常情况下,把具有相同性质的一类东西,汇聚成一个整体,就可以称为集合。 Java集合框架均在java.util包中。

虚线框表示接口。
实线框表示实体类。
粗线框表示最常用的实体类。
点线的箭头表示实现接口。
实线箭头表示类可以制造箭头所指的那个类的对象。

1.Java集合框架的主要接口

2.迭代接口Iterable与迭代器接口Iterator
为了遍历Collection 集合元素,Java 引入了Iterable 类型(Iterable 表示可迭代之意)。
接口java.lang.Iterable 的抽象方法iterator() 返回一个接口Iterator 类型的对象。第一次调用接口Iterator 的next() 方法时,它返回序列的第一个元素。
3.泛型
泛型是 Java SE 1.5 版本之后的新特性。在Java SE 1.5 版本之前,Java 通过对类型Object 的引用来实现参数类型的“任意化”,特点则是需要进行显式的强制类型转换,但编译器无法发现强制类型转换可能引起的异常,异常只有在运行时才出现,这将成为系统的安全隐患。
如今,在Java 集合框架的API 中,绝大部分接口和类都已经泛型化。事实上,在eclipse-jee 中,通过链接跟踪方式,可以打开接口List 的源码如下:

不指定实际类型(用字母代替),实现广泛意义上的操作
4.Collection集合
Collection是最基本的集合接口,一个Collection代表一组Object(注意:集合必须只有对象,集合中的元素不能是基本数据类型)。
Collection 是一组允许重复的对象,对象之间没有指定的顺序。


注意:Collection仅仅是一个接口,而真正使用的时候,是创建该接口的一个实现类(如ArrayList)。
5.迭代器接口Iterator
Iterator(迭代器)的功能就是遍历并选择集合序列中的对象,而程序员不必知道该序列底层的结构。
创建迭代器的代价很小(轻量级),但是,它也有一些限制,例如,某些迭代器只能单向移动。
基本操作
(1)boolean hasNext():是否存在另一个可访问的元素。
(2)Object next():返回要访问的下一个元素。
(3)void remove():将迭代器新返回的元素删除。
注意:remove()必须紧跟在next()方法后执行,在每次调用next()时,remove方法只能被调用一次。
基本用法--遍历一个集合
1 | Iterator it = Collection集合对象.iterator(); // 获得迭代器 |
6.List集合
List继承了 Collection 接口,以定义一个允许重复项的有序集合。
List 是按对象的进入顺序进行保存对象,而不做排序或编辑操作。
List除了拥有Collection接口的所有的方法外,还添加了面向位置的操作方法。
面向位置的操作包括插入某个元素或 Collection 的功能;
还包括获取、除去或更改元素的功能;
在 List 中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。

List迭代器
ListIterator listIterator() 返回一个ListIterator 迭代器,默认开始位置为0。
ListIterator listIterator(int startIndex) 返回一个ListIterator 迭代器,开始位置为startIndex。
ListIterator 接口继承了 Iterator 接口
支持添加或更改底层集合中的元素
支持双向访问
基本用法
--逆向遍历
1 | ListIterator it = list.listIterator( list.size() ); // list为一个List对象 |
List的两个常用实现
ArrayList 线性表:
ArrayList封装了一个动态再分配的Object[ ]数组。
每个ArrayList对象有一个capacity,表示存储列表中元素数组的容量。当元素添加到ArrayList时,它的capacity将自动增加。
在向一个ArrayList对象添加大量元素时,可使用ensureCapacity()方法增加capacity。
(1)void ensureCapacity(int minCapacity):将ArrayList对象容量增加minCapacity
(2)void trimToSize():整理ArrayList对象容量为列表当前大小,使用该操作减少ArrayList对象存储空间。
LinkedList链表
LinkList添加了一些处理列表两端元素的方法:
(1)void addFirst(Object o):将对象o添加到列表的开头 void addLast(Object o):将对象o添加到列表的结尾
(2)Object getFirst():返回列表开头的元素 Object getLast():返回列表结尾的元素
(3)Object removeFirst():删除并返回列表开头的元素 Object removeLastt():删除并返回列表结尾的元素
(4)LinkedList():创建一个空的链接列表 LinkedList(Collection c):创建一个链接列表,并添加集合c所有的元素
7.Set集合
Set 接口继承 Collection 接口,而且它不允许集合中存在重复项。
Set接口没有引入新方法,每个具体的 Set 实现类依赖添加的对象的 equals() 方法来检查独一性。即任意的两个元素e1和e2都有e1.equals(e2)=false。

hashset喝treeset都是按值从小到大
linkedhashset是按插入顺序
8.队列接口Queue
队列接口 Queue 继承Collection接口,用来表示先入先出(FIFO)的数据结构。
LinkedList 类是List 接口的实现类,同时也是Queue 接口的实现类,因此,可以使用LinkedList 类来创建队列。
9.Map集合
映射这种数据结构含有两个部分:关键字和值。对于每个关键字都有一个值,也就是说,一个关键字映射一个值。映射允许通过关键字访问数据结构。
Map接口中声明了一对一的映射。当向映射中插入一对关键字和值时,如果出现关键字重用,则用新值替换映射中原有的值,不在映射中增加一个元素。
接口Map 并未继承接口Iterable,这与接口Collection 不同。接口Map **提供了返回值类型为Set< Entry<K,V>>的方法entrySet()**。Entry<K,V>是接口Map 的内部接口,表示Map集合项,并提供了从集合项中获取键名的方法getKey() 和获取键值的方法getValue() 等。
因为是对Set< Entry<K,V>>应用迭代器,所以,可以认为Map 接口间接实现了Iterable 接口。




hashmap、treemap输出是按键从小到大
linkedhashmap是按输入顺序
10.排序—Comparable接口
对于存储在集合里的自定义对象,要想对它们进行排序,我们只需要让它们实现相应的比较接口java.lang.Comparable,并且实现(重写)该接口里面的一个比较方法compareTo(Object o)
然后调用**java.util.Collections.sort(List list)**方法,Java就会按照它的一套方法对List集合里面的对象排列先后次序。
int compareTo(Object o)方法:
0,表示当前对象应该排在方法中传过来对象的前面;
<0,表示当前对象应该排在方法中传过来对象的后面;
=0,表示两个对象并列。
重写compareTo目的:定义比较规则,使集合中的对象可以互相比较

Comparator接口

Comparator示例
1 | import java.util.*; |
之后再使用sort即可实现排序
可见ppt第五章52页示例
比较:



八.Java 网络编程
1.传输协议–TCP和UDP
TCP:一种面向连接的保证可靠传输的协议。(Tranfer Control Protocol)
1)通过TCP协议传输,得到的是一个顺序的无差错的数据流。
2)发送方和接收方的两个Socket之间必须建立连接,当一个Socket(通常都是Server Socket)等待建立连接时,另一个Socket可以要求进行连接,一旦这两个Socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
3)一旦连接建立起来,双方的Socket就可以按统一的格式传输大量的数据。
4)TCP传输的效率不如UDP高。
UDP:一种面向无连接不保证可靠传输的协议。 (User Datagram Protocol)
1)每个数据报中都给出了完整的地址信息,因此无需要建立发送方和接收方的连接。
2)数据报在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
3)使用UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在64KB之内。
2.HTTP连接
1)在传输数据时,可以只使用传输层的TCP或UDP 协议。此时,便无法识别数据内容。如果想要使传输的数据有意义(如在B/S体系中,使用HTTP协议后,有请求报文和响应报文等),则必须使用应用层协议。应用层协议有很多,如HTTP(HyperText Transfer Protocol,超文本传输协议)、FTP(File Transfer Protocol,文件传输协议)TELNET(远程登录协议)等。当然,也可以自己定义应用层协议。
2)HTTP 连接最显著的特点之一是客户端发送的每次请求都需要服务器回送响应,在请求结束后,主动释放连接。
3.Socket:概念
Socket概念网络上的两个应用程序之间的通信是分层进行的。
Socket是应用程序进行网络通信的接口。

如果要发起网络连接,不仅需要知道远程机器的地址或名字。而且,还需要一个端口号。客户端和服务器必须事先约定所使用的端口,如果系统两部分所使用的端口不一致,那就不能进行通信
工作原理
Server端Listen(监听)某个端口是否有连接请求,Client端向Server端发出Connect(连接)请求,Server端向Client端发回Accept(接受)消息,一个连接就建立起来了。Server端和Client端都可以通过send()和write()等方法与对方通信。
四个基本的步骤:
(1) 创建Socket;
(2) 打开连接到Socket的输入/出流;
(3) 按照一定的协议对Socket进行读/写操作;
(4) 关闭Socket。
4.基于TCP或UDP的Socket通信
1)Socket 是对TCP、UDP协议的封装,是一个调用接口(API),通过Socket而使用TCP/UDP协议。
2)Socket 本身并不是协议,它只是提供了一个针对 TCP 或UDP 编程的接口。Socket 是对端口通信开发的工具,它比TCP或UDP通信更加底层。

TCP服务器端TCPServer.java
1 | ServerSocket serverSocket=null; |
字节流要close
seversocket再close
ServerSocket的accept()方法:
从连接请求队列中取出一个客户的连接请求,然后创建与客户连接的Socket对象,并将它返回。如果队列中没有连接请求,accept()方法就会一直等待,直到接收到了连接请求才返回。
TCP客户端TCPClient.java
1 | try{ |
对于OutputStream字节流,还可以用DataOutputStream封装:
OutputStream os = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(sendString);
对于InputStream字节流,还可以用DataInputStream封装:
InputStream is = socket.getInputStream();
DataInputStream dis = new DataInputStream(is);
System.out.println( dis.readUTF() );


5.UDP Socket
用户数据报协议(User Datagram Protocol,UDP)是一种无连接协议。UDP 编程涉及数据报文包DatagramPacket 及相关类,其定义如图8.2.2 所示。

使用多线程支持多客户端
前面提供的Client/Server程序只能实现Server和一个客户的对话。
Server端利用多线程实现多客户机制。服务器总是在指定的端口上监听是否有客户请求,一旦监听到客户请求,服务器就会启动一个专门的服务线程来响应该客户的请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。

服务器端代码:
1 | class ServerThread extends Thread{ |




本文链接: http://wusterlllry.xyz/2023/12/13/Java/
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!