java笔记(4)

***62.IO流 注意:在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。
(1)•按照操作分
1).字节流: 以字节为单位来操作数据. 字节流能操作所有的文件类型. 例如: 图片, 视频, 音频, 文本文件等.
字节输入流 顶层抽象类是: InputStream. –字节输出流 顶层抽象类是: OutputStream.
2).字符流: 以字符为单位来操作数据. 字符流只能操作纯文本文件 顶层抽象类是: Writer.
字符输入流 顶层抽象类是: Reader –字符输出流
3).简单理解: 如果某个文件能用操作系统自带的记事本打开, 并且里边的内容你也能读得懂, 就可以考虑使用字符流, 否则, 使用字节流.
(2)FileOutputStream介绍
1).构造方法
•public FileOutputStream(String name)
创建普通的字节输出流对象, 关联目的地文件(字符串形式).如果文件中有数据, 当程序启动之后并往文件中写入数据时, 文件中已有的数据会被覆盖掉.
• public FileOutputStream(File file)
创建普通的字节输出流对象, 关联目的地文件(File对象形式). 如果文件中有数据, 当程序启动之后并往文件中写入数据时, 文件中已有的数据会被覆盖掉.
• public FileOutputStream(String name, boolean append)
创建普通的字节输出流对象, 关联目的地文件(字符串形式).当append的值为true时, 表示往文件中追加数据, 即: 文件中的数据不会被覆盖掉.
• public FileOutputStream(File file, boolean append)
创建普通的字节输出流对象, 关联目的地文件(File对象形式). 当append的值为true时, 表示往文件中追加数据, 即: 文件中的数据不会被覆盖掉.
2)成员方法
• public void write(int b)
解释: 一次写入一个字节, 到指定的目的地文件中.
• public void write(byte[] bys)
解释: 一次写入一个字节数组, 到指定的目的地文件中.
• public void write(byte[] bys, int start, int len)
解释: 一次写入一个字节数组的一部分, 到指定的目的地文件中.
• public void close()
解释: 关闭此文件输出流并释放与此流相关联的任何系统资源.
(3)FileInputStream介绍 FileInputStream表示普通的字节输入流, 用来以字节的形式从文件中读取数据.
1)构造方法
• public FileInputStream(String name)
解释: 创建普通的字节输入流对象, 关联数据源文件(字符串形式).
• public FileInputStream(File file)
解释: 创建普通的字节输入流对象, 关联数据源文件(File对象形式).
2)成员方法 skip() 跳过几个字节
• public int read()
解释: 从指定的数据源文件中, 一次读取一个字节, 并返回该字节对应的整数. 读不到则返回-1.
• public int read(byte[] bys)
解释:
1.从指定的数据源文件中, 一次读取一个字节数组, 并将读取到的内容存入到字节数组中.返回读取到的有效字节数. 如果读不到则返回-1.
• public void close()
解释: 关闭此文件输入流并释放与此流相关联的任何系统资源.
(4)将项目下的1.txt中的内容复制到2.txt文件中.
IO流的核心6步操作.
1. 创建输入流对象, 关联数据源文件.
2. 创建输出流对象, 关联目的地文件.
3. 定义变量, 记录读取到的内容或者有效字节(符)数.
4. 循环读取,只要条件满足就一直读, 并将读取到的内容赋值给变量.
5. 将读取到的内容写入到目的地文件中.
6. 关流, 释放资源.
(5)字节缓冲流主要分为两个:• BufferedInputStream: 字节缓冲输入流 • BufferedOutputStream: 字节缓冲输出流
1)构造方法
• BufferedOutputStream类的构造方法
–public BufferedOutputStream(OutputStream os) 创建字节缓冲输出流对象,
• BufferedInputStream类的构造方法
–public BufferedInputStream(InputStream is) 创建字节缓冲输入流对象.
注意:字节缓冲流仅仅提供缓冲区, 而真正的底层的读写数据还是需要基本的流对象进行操作
2)小细节: 因为字节缓冲流提供的缓冲区的大小是: 8196个字节(8KB), 所以如果我们用 普通流一次读写一个字节数组的方式拷贝文件,且自定义的数组
长度在 8196个字节, 那么可能会出现: 普通流一次读写一个字节数组的速度 > 高效流一次读写一个字节数组的速度
(6)字符流
1)字符输出流:Writer类
FileWriter类中的方法: FileWriter类中的方法全部都是来自于父类
write(char ch) 一次写入一个字符
write(char[] cbuf, int off , int len) 一次向文件中写入多个字符数据。
说明:把char[]数组中从off角标开始取len长度个字符一次性写入
write(String str) 把字符串写入到文件中
write(String str, int off , int len) 写入字符串的某一部分
flush() 把字符输出流中内置缓冲区下的字节数据,写入到文件中(刷新流)
close() 由于每个IO流都需要绑定一个IO资源,在使用时,需要回收资源。而字符流输出流在关闭时,会先调用flush方法
2)字符输入流 :Reader
FileReader类中的常用方法:
int read():读取一个字符; (使用int代替char)
int read(char[] c):读取一个字符数组;
close():由于每个IO流都需要绑定一个IO资源,在使用后,需要回收资源。
3)字符缓冲流
•BufferedWriter类的构造方法
public BufferedWriter(Writer w) 创建字符缓冲输出流对象,
• BufferedReader类的构造方法
public BufferedReader(Reader r) 创建字符缓冲输入流对象.
•BufferedWriter类中的特有的方法
public void newLine(); 根据当前操作系统, 给出对应的换行符.
• BufferedReader类中的特有的方法
public String readLine(); 读取一行数据, 只包含数据, 不包含任何终止字符, 如果读到流末尾, 则返回null.

  •   		注意;关闭字符流之前会先调用flush方法刷新.字节流可以不需要
    

    (7)对象序列化流 : ObjectOutputStream
    1)介绍:就是将对象保存到磁盘中,或者在网络中传输对象这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性
    等信息字节序列写到文件之后,相当于文件中持久保存了一个对象的信息反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化.
    将Java对象的原始数据类型和图形写入OutputStream。可以使用ObjectInputStream读取(重构)对象。 可以通过使用流的文件来实现对象的持久存储。
    如果流是网络套接字流,则可以在另一个主机上或另一个进程中重构对象 .
    2)构造方法
    ObjectOutputStream(OutputStream out) 创建一个写入指定的OutputStream的ObjectOutputStream
    3)方法
    void writeObject(Object obj) 将指定的对象写入ObjectOutputStream
    ** 注意:想要序列化的类,必须要实现一个接口.serializable 这个接口是一个标记型接口 仅仅作为一个标记存在.
    (8)对象反序列化流: ObjectInputStream
    1)介绍:ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
    2)构造方法 : ObjectInputStream(InputStream in) 创建从指定的InputStream读取的ObjectInputStream
    3)反序列化对象的方法 : Object readObject() 从ObjectInputStream读取一个对象
    注意:serialVersionUID 序列化版本号,用来识别序列化与反序列化的类是否是同一个.
    序列化版本号是根据类中的内容生成的,修改类中的内容,序列化版本号会发生变化. 可以人为的写死版本号(用static final修饰)
    序列化中的内容反序列化时,更改后的类中,原先是什么还是赋值什么,反序列化后面添加的元素值为默认值,后面删除的元素值反序列化之后就不赋值.
    3)transient 对于不想反序列化的内容用瞬态修饰,可以隐藏该成员

    (9)总结
    1)所有的流都实现了:
    java.io.Closeable接口,都是可关闭的,都有close()方法。
    流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
    2)所有的输出流都实现了:
    java.io.Flushable接口,都是可刷新的,都有flush()方法。
    养成一个好习惯,输出流在最终输出之后,一定要记得flush()刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据强行输出完(清空管道!)刷新的作用就是清空管道。
    注意:如果没有flush()可能会导致丢失数据。
    3)java.io包下需要掌握的流有16个:
    文件专属:
    java.io.FileInputStream(掌握)
    java.io.FileOutputStream(掌握)
    java.io.FileReader
    java.io.FileWriter
    转换流:(将字节流转换成字符流)
    java.io.InputStreamReader
    java.io.OutputStreamWriter
    缓冲流专属:
    java.io.BufferedReader
    java.io.BufferedWriter
    java.io.BufferedInputStream
    java.io.BufferedOutputStream
    数据流专属:
    java.io.DataInputStream
    java.io.DataOutputStream
    标准输出流:
    java.io.PrintWriter
    java.io.PrintStream(掌握)
    对象专属流:
    java.io.ObjectInputStream(掌握)
    java.io.ObjectOutputStream(掌握)
    注意:在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。

63.多线程
(1)线程有两种调度模型:
分时调度模型 :所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片。
抢占式调度模型 :优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些。
Java使用的是抢占式调度模型: (线程的优先级是在创建线程时,给线程指定好的)
*** (2)多线程的实现:
1)第一种方式:继承Thread,重写run方法 [调用线程对象的start()方法来启动该线程]
[Thread中有一个方法getName 获取线程名字,命名规则:从Thread0-Thread9999…]
2)第二种方式:实现Runnable接口,实现run方法,在创建实现类对象,在将实现类对象作为参数传给Thread(这种方式是推荐的)
步骤:1.定义Runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体
2. 创建Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象
3. 调用线程对象的start()方法来启动线程
[static Thread currentThread() 返回正在运行的线程对象,即使用 Thread.currentThread.getName()]
注意:Runnable对象仅仅作为Thread对象的target.Runnable实现类里包含的run()方法仅作为线程执行体。
而实际的线程对象依然是Thread实例,只是该Thread线程负责执行其target的run()方法
(3)Thread类
构造方法:
public Thread() 分配一个新的线程对象

  •   public Thread(String name)	分配一个指定名字的新的线程对象
      public Thread(Runnable target)	分配一个带有指定目标新的线程对象
      public Thread(Runnable target,String name)	分配一个带有指定目标新的线程对象并指定名字
    

** 常用方法:
public String getName() 获取当前线程名称
public void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法
public void run() 此线程要执行的任务在此处定义代码 [run方法的父类没用抛出异常,在run方法里不能抛弃异常]
public static Thread currentThread() 返回对当前正在执行的线程对象的引用
public static void sleep(long millis) 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行) 在main方法里就是main方法休眠
interrupt()方法,中断子线程的睡眠(这种方式是依靠java的异常处理机制)
stop()方法可以强行终止一个线程的执行.缺点:容易丢数据,因为是直接将进程杀死. 线程没有保存的数据会丢失.
合理的方法加一个if判断语句,加个布尔类型的标记
(4)Thread和Runnabel的区别
实现Runnable接口比继承Thread类所具有的优势:
1.适合多个相同的程序代码的线程去共享同一个资源。
2.可以避免java中的单继承的局限性。
3.增加程序的健壮性,实现解耦操作,任务代码可以被多个线程共享,任务代码和线程独立。
4.线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
(5)通过实现Runnable接口,使得该类有了多线程类的特征。run()方法是多线程程序的一个执行目标。所有的多线程代码都在run方法里面。Thread类实际
上也是实现了Runnable接口的类。在启动的多线程的时候,需要先通过Thread类的构造方法Thread(Runnable target) 构造出对象,然后调用Thread对象的
start()方法来运行多线程代码。实际上所有的多线程代码都是通过运行Thread的start()方法来运行的。因此,不管是继承Thread类还是实现Runnable接口
来实现多线程,最终还是通过Thread的对象的API来控制线程的,熟悉Thread类的API是进行多线程编程的基础。
(6)线程安全:
什么时候数据在多线程并发的环境下会存在安全问题呢?
三个条件:条件1:多线程并发。条件2:有共享数据。条件3:共享数据有修改的行为。满足以上3个条件之后,就会存在线程安全问题。
如果有多个线程在同时运行,而这些线程可能会同时运行这段代码。程序每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
简单来讲:就是多线程程序的执行结果,和使用单线程程序的执行结果要相同 如果结果不同,那就表示多线程程序,存在线程不安全.
线程安全问题都是由全局变量及静态变量引起的。若每个线程中对全局变量、静态变量只有读操作,而无写操作(修改值),一般来说,这个全局变量是线程安全
的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
(7)线程同步: 局部变量永远都不会存在线程安全问题
1)异步编程模型:
线程t1和线程t2,各自执行各自的,t1不管t2,t2不管t1,谁也不需要等谁,这种编程模型叫做:异步编程模型。
其实就是:多线程并发(效率较高。)异步就是并发。
2)同步编程模型:
线程t1和线程t2,在线程t1执行的时候,必须等待t2线程执行结束,或者说在t2线程执行的时候,必须等待t1线程执行结束,
两个线程之间发生了等待关系,这就是同步编程模型。效率较低。线程排队执行。同步就是排队。
1 同步代码块 针对方法体中的代码
只需要方法体中的部分代码使用同步机制时,使用:同步代码
同步代码块:synchronized关键字可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问
书写格式: synchronized(同步锁){ 需要同步操作的代码 }
2 同步方法 针对当前整个方法
使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。
书写格式: public synchronized void method(){ 可能会产生线程安全问题的代码 }
同步锁是谁? 对于非static方法,同步锁就是this. 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)
(8)线程池
1) 概述: 有了多线程技术, 服务器端就可以同时为多个客户端提供服务, 但是线程运行结束后就会死亡, 频繁创建新的线程, 会导致系统开销过大, 因此Java
在JDK5版本中引入了线程池概念. 将多个线程对象存储到容器中, 用的时候从容器中取出, 使用完毕后再放回,这样可以大大减少系统开销
2)实现方式一
JDK提供的线程池并不是直接创建对象,而是用工厂类创建线程池对象。
• 线程池工厂类:Executors
– public static ExecutorService newFixedThreadPool(int nThreads)
方法解释: 线程池工厂类创建固定线程数的方法
• 线程池接口:ExecutorService
– public Future<?> submit(Runnable task)
方法解释: 使用线程池对象方法submit提交线程执行任务,这是实现多线程的第三种方式
– public void shutdown()
方法解释: 关闭线程池
3)实现方式二 :
JDK5以后, 实现多线程有了一种新的方式, 即: 通过Callable接口实现
好处:• 线程执行后, 可以具有返回值. • 可以抛出异常.
弊端:• 该方式只能结合线程池一起使用.
涉及到的API
• 线程池工厂类:Executors
– public static ExecutorService newFixedThreadPool(int nThreads)
方法解释: 线程池工厂类创建固定线程数的方法
– public static ExecutorService newCachedThreadPool()
方法解释: 创建一个可根据需要创建新线程的线程池
• 线程池接口:ExecutorService
– public Future<?> submit(Runnable task)
方法解释: 使用线程池对象方法submit提交线程执行任务,这是实现多线程的第三种方式
– public Future submit(Callable task)
方法解释: 使用线程池对象方法submit提交线程执行任务,这是实现多线程的第三种方式 提供get方法来获取callable任务类返回值
– public void shutdown()
方法解释: 关闭线程池
(9)java中提供了一些方法和线程调度有关系的
实例方法:
void setPriority(int newPriority) 设置线程的优先级
int getPriority() 获取线程优先级 最低优先级1,默认优先级是5,最高优先级10
优先级比较高的获取CPU时间片可能会多一些。(但也不完全是,大概率是多的。)
静态方法:
static void yield() 让位方法暂停当前正在执行的线程对象,并执行其他线程.
yield()方法不是阻塞方法。让当前线程让位,让给其它线程使用。yield()方法的执行会让当前线程从“运行状态”回到“就绪状态”。
注意:在回到就绪之后,有可能还会再次抢到。
void join() 合并线程 t.join(); // 当前线程进入阻塞,t线程执行,直到t线程结束。当前线程才可以继续。 [t为对象]
(10)死锁 synchronize进行嵌套使用导致的. 如:a,b2个线程共享2个成员变量c,d.a是先锁c,在锁d,b是先锁d,在锁c.
*** (11)开发中应该怎么解决线程安全问题:
第一种方案:尽量使用局部变量代替“实例变量和静态变量”。
第二种方案:如果必须是实例变量,那么可以考虑创建多个对象,这样实例变量的内存就不共享了。(一个线程对应1个对象,100个线程对应100个对象,对象不共享,就没有数据安全问题了。)
第三种方案:如果不能使用局部变量,对象也不能创建多个,这个时候就只能选择synchronized了。线程同步机制。
(12)线程这块还有那些内容呢?列举一下
1)守护线程 语法: 对象.setDaemon(true); //需要在启动线程之前,将线程设置为守护线程
java语言中线程分为两大类:
一类是:用户线程
一类是:守护线程(后台线程) Timer timer=new Timer(true) //守护线程的方式
其中具有代表性的就是:垃圾回收线程(守护线程)。
守护线程的特点:一般守护线程是一个死循环,所有的用户线程只要结束,守护线程自动结束。
注意:主线程main方法是一个用户线程。
守护线程用在什么地方呢?
每天00:00的时候系统数据自动备份。这个需要使用到定时器,并且我们可以将定时器设置为守护线程。
一直在那里看着,每到00:00的时候就备份一次。所有的用户线程如果结束了,守护线程自动退出,没有必要进行数据备份了。
*** 2)定时器 schedule(定时任务,第一次执行时间,间隔多久执行一次)方法
定时器的作用:
间隔特定的时间,执行特定的程序。每周要进行银行账户的总账操作。每天要进行数据的备份操作。
在实际的开发中,每隔多久执行一段特定的程序,这种需求是很常见的,那么在java中其实可以采用多种方式实现:
可以使用sleep方法,睡眠,设置睡眠时间,没到这个时间点醒来,执行任务。这种方式是最原始的定时器。(比较low)
在java的类库中已经写好了一个定时器:java.util.Timer,可以直接拿来用。
不过,这种方式在目前的开发中也很少用,因为现在有很多高级框架都是支持定时任务的。
在实际的开发中,目前使用较多的是Spring框架中提供的SpringTask框架,这个框架只要进行简单的配置,就可以完成定时器的任务。
3)实现线程的第三种方式:实现Callable接口。(JDK8新特性。)
这种方式实现的线程可以获取线程的返回值。之前的那两种方式是无法获取线程返回值的,因为run方法返回void。
系统委派一个线程去执行一个任务,该线程执行完任务之后,可能会有一个执行结果,我们怎么能拿到这个执行结果呢?
使用第三种方式:实现Callable接口方式。
4)关于Object类中的wait和notify方法。(生产者和消费者模式!) 是多线程共享的对象去调用这2个方法
第一:wait和notify方法不是线程对象的方法,是java中任何一个java对象都有的方法,因为这两个方式是Object类中自带的。
wait方法和notify方法不是通过线程对象调用,不是这样的:t.wait(),也不是这样的:t.notify()…不对。 通过java对象调用
第二:wait()方法作用?
Object o = new Object(); o.wait();
表示:让正在o对象上活动的线程进入等待状态,无期限等待,直到被唤醒为止。o.wait();方法的调用,会让“当前线程(正在o对象上活动的线程)”进入等待状态。
第三:notify()方法作用?
Object o = new Object();o.notify();
表示:唤醒正在o对象上等待的线程。还有一个notifyAll()方法:这个方法是唤醒o对象上处于等待的所有线程。
注意:o.wait()方法会让正在o对象上活动的当前线程进入等待状态,并且释放之前占有o对象的锁. o.notify()方法只会通知,不会释放之前占有的o对象的锁.

64.网络编程
(1)软件结构
1)C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。
2)B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。
(2)网络编程三要素
1)协议
协议:计算机网络通信必须遵守的规则。
协议对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。常见的协议有UDP协议和TCP协议
TCP/IP协议:传输控制协议/因特网互联协议( Transmission Control Protocol/Internet Protocol),是Internet最基本、最广泛的协议。
2)IP地址
IP地址:指互联网协议地址(Internet Protocol Address),俗称IP。
传统的TCP/IP协议基于IPV4属于第二代互联网技术,核心技术属于美国。它的最大问题是网络地址资源有限,从理论上讲,编址1600万个网络、40亿台主
机。但采用A、B、C三类编址方式后,可用的网络地址和主机地址的数目大打折扣,以至IP地址已经枯竭。
3)端口号:如果说IP地址可以唯一标识网络中的设备,那么端口号就可以唯一标识设备中的进程(应用程序)了。
端口号用两个字节表示的整数,它的取值范围是065535。其中,01023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024
以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。(很多程序在安装时,是允许用户自定义端口号[会先给一个默认的端口号])
利用协议+IP地址+端口号 三元组合,就可以标识网络中的进程了,那么进程间的通信就可以利用这个标识与其它进程进行交互。
(3)InetAddress 表示表示Internet协议(IP)地址
static InetAddress getByName(String host) 确定主机名称的IP地址。主机名称可以是机器名称,也可以是IP地址
string getHostName() 获取此IP地址的主机名
string getHostAddress() 返回文本显示中的IP地址字符串
(4)UDP 传输的最大数据为64k
DatagramSocket() 创建数据报套接字并将其绑定到本机地址上任何可用的端口
DatagramPacket(byte[] buf,int length,InetAddress address ,int port) 数据报包
(5) TCP
1)概述
TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)
两端通信时步骤:
1、服务端程序,需要事先启动,等待客户端的连接
2、客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。
在Java中,提供了两个类用于实现TCP通信程序:
1、客户端:java.net.Socket 类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
2、服务端:java.net.ServerSocket 类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。
2)Socket类 : 该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。
构造方法
public Socket(String host, int port) : 创建套接字对象并将其连接到指定主机上的指定端口号。如果指定的host是null,则相当于指定地址为
回送地址。参数:host, IP地址 port, 端口号
构造举例,代码如下: Socket client = new Socket(“127.0.0.1”, 6666);
成员方法
public InputStream getInputStream() : 返回此套接字的输入流。
如果此Scoket具有相关联的通道,则生成的InputStream 的所有操作也关联该通道。关闭生成的InputStream也将关闭相关的Socket。
public OutputStream getOutputStream() : 返回此套接字的输出流。
如果此Scoket具有相关联的通道,则生成的OutputStream 的所有操作也关联该通道。关闭生成的OutputStream也将关闭相关的Socket。
public void close() :关闭此套接字。一旦一个socket被关闭,它不可再使用。关闭此socket也将关闭相关的InputStream和OutputStream 。
public void shutdownOutput() : 禁用此套接字的输出流。 任何先前写出的数据将被发送,随后终止输出流。
4)ServerSocket类: 这个类实现了服务器套接字,该对象等待通过网络的请求
构造方法
public ServerSocket(int port) :使用该构造方法在创建ServerSocket对象时,就可以将其绑定到一个指定的端口号上,参数port就是端口号
构造举例,代码如下: ServerSocket server = new ServerSocket(6666);
成员方法
public Socket accept() :侦听并接受连接,返回一个新的Socket对象,用于和客户端实现通信。该方法会一直阻塞直到建立连接
5)TCP通信分析图解
1、【服务端】启动,创建ServerSocket对象,等待连接。
2、【客户端】启动,创建Socket对象,请求连接。
3、【服务端】接收连接,调用accept方法,并返回一个Socket对象。
4、【客户端】Socket对象,获取OutputStream,向服务端写出数据。
5、【服务端】Scoket对象,获取InputStream,读取客户端发送的数据。
到此,客户端向服务端发送数据成功
6、【服务端】Socket对象,获取OutputStream,向客户端回写数据。
7、【客户端】Socket对象,获取InputStream,解析回写数据。
8、【客户端】释放资源,断开连接。
自此,服务端向客户端回写数据成功

65.Junit
1. 编写测试类,简单理解Junit可以用于取代java的main方法
2. 在测试类方法上添加注解:@Test
3. @Test修饰的方法要求:public void 方法名() {…} ,方法名自定义建议test开头,没有参数。
4. 添加Junit库到lib文件夹中,然后进行jar包关联
5.添使用:点击方法左侧绿色箭头,执行当前方法(方法必须标记@Test)。执行结果红色:代表失败;执行结果绿色:代表成功

66.反射
(1)概述: Java 反射机制是程序在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属
性;这种动态获取的信息以及动态调用对象的方法的功能称为 java 的反射机制.
(2)反射的作用:可以动态的对类进行编译以及动态的创建对象。
(3)反射的应用场景:程序在运行时,前期并不需要使用过多的类,那么一些暂时不使用的类,就不需要加载到JVM中去(可以提升JVM的执行性能),而随着程序的
运行,运行的程序会根据需要动态的加载这些类。
(4)Java中实现反射的步骤:
第1步:获得相应的.class文件,也就是Class对象
第2步:利用Class,来实例化对象
第3步:通过实例化的对象,来调用成员方法/属性
(5)class
1)获取class对象方式 作用 应用场景
**** Class.forName(“全类名”) 通过指定的字符串路径获取 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
类名.class 通过类名的属性class获取 当明确了具体的类型时
对象名.getClass() 通过对象的getClass()方法获取 在方法内部通过参数获得类型
2)Class类中常用的方法:
String getSimpleName(); //获得简单类名,只是类名,没有包
String getName(); //获取完整类名,包含包名+类名
** T newInstance();//创建此 Class 对象所表示的类的一个新实例。要求:类必须有public的无参数构造方法
(6)Constructor
1)获取Constructor类对象:
**** getXXX 获取公共的 getDeclaredXxx 获取任意访问权限
**** Field(成员属性) Constructor(构造方法) Method(成员方法)
1. Constructor getConstructor(Class… parameterTypes)
根据参数类型获取构造方法对象,只能获得public修饰的构造方法。如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。
2. Constructor getDeclaredConstructor(Class… parameterTypes)
根据参数类型获取构造方法对象,包括private修饰的构造方法。如果不存在对应的构造方法,则会抛出 java.lang.NoSuchMethodException 异常。
3. Constructor[] getConstructors() 获取所有的public修饰的构造方法(不包含私有的构造方法)
4. Constructor[] getDeclaredConstructors() 获取所有构造方法,包括privat修饰的
2)Constructor类常用方法:
** 1. T newInstance(Object… initargs) 根据指定参数创建对象。参数是:可变参数
** 2. void setAccessible(true) 去除私有权限. 暴力反射,设置为可以直接访问私有类型的构造方法。
****(7)Method成员方法
1)获取Method类对象:
1. Method getMethod(“方法名”, 方法的参数类型… 类型) 根据方法名和参数类型获得一个方法对象,只能是获取public修饰的
2. Method getDeclaredMethod(“方法名”, 方法的参数类型… 类型) 根据方法名和参数类型获得一个方法对象,包括private修饰的
3. Method[] getMethods() 获取所有的public修饰的成员方法,包括父类中。
4. Method[] getDeclaredMethods() 获取当前类中所有的方法,包含私有的,不包括父类中。
2)Method类中常用方法:
1. Object invoke(Object obj, Object… args) 根据参数args调用对象obj的该成员方法.如果obj=null,则表示该方法是静态方法
2. void setAccessible(boolean flag) 暴力反射,设置为可以直接调用私有修饰的成员方法
(8)Properties
java.util.Properties 继承于Hashtable ,来表示一个持久的属性集(K-V)。Properties使用键值结构存储数据,每个键及其对应值都是一个字符串。
构造方法:
public Properties() : 创建一个空的属性列表
常用方法:
public Object setProperty(String key, String value) : 保存一对属性
public String getProperty(String key) :使用此属性列表中指定的键搜索属性值
public Set stringPropertyNames() :所有键的名称的集合

零碎知识点:
UUID.randomUUID()方法可以随机产生不重复的id.
BigDecimal 属于大数据,精度极高.在java.math.BigDecimal包下,要想用,先new 对象,求和的话需要在用另外一个新=对象1.add(对象2)
如: BigDecimal v1=new BigDecimal(100);BigDecimal v2=new BigDecimal(200); BigDecimal v3=v1.add(v2); [都是引用数据类型]

随机数
4.1、怎么产生int类型随机数。
Random r = new Random();
int i = r.nextInt();
4.2、怎么产生某个范围之内的int类型随机数。
Random r = new Random();
int i = r.nextInt(101); // 产生[0-100]的随机数。

枚举
5.1、枚举是一种引用数据类型。
5.2、枚举编译之后也是class文件。
5.3、枚举类型怎么定义?
enum 枚举类型名{
枚举值,枚举值2,枚举值3
}
5.4、当一个方法执行结果超过两种情况,并且是一枚一枚可以列举出来
的时候,建议返回值类型设计为枚举类型。

什么是UML?有什么用?
UML是一种统一建模语言。
一种图标式语言(画图的)
UML不是只有java中使用。只要是面向对象的编程语言,都有UML。
一般画UML图的都是软件架构师或者说是系统分析师。这些级别的人员使用的。软件设计人员使用UML。
在UML图中可以描述类和类之间的关系,程序执行的流程,对象的状态等.盖大楼和软件开发一样,一个道理。
盖楼之前,会先由建筑师画图纸。图纸上一个一个符号都是标准符号。
这个图纸画完,只要是搞建筑的都能看懂,因为这个图纸上标注的这些符号都是一种“标准的语言”。
在java软件开发当中,软件分析师/设计师负责设计类,java软件开发人员必须要能看懂。

字节码文件就是你硬盘上的.class文件,硬盘上的.class文件加载到方法区叫字节码对象.

引用等于null的这个判断最好放到所有条件的最前面.
usernamenull 不如写成nullusername
“abc”.equals(username)比usernam.equals(“abc”)好

集合里的contains方法是调用equals方法,看是否重写equals方法,String类型是判断内容而不是地址

*** ArrayList集合初始化容量10,扩容为原容量1.5倍。底层是数组。建议给定一个预估计的初始化容量,减少数组的扩容次数,这是ArrayList集合比较重要的优化策略.
LinkedList集合底层采用了双向链表数据结构
Vector集合底层采用了数组结构,他是线程安全的.他所有方法都有synchronized关键字修饰,但是效率低. Vector初始化容量是10.扩容为原容量的2倍。
HashSet集合在new的时候,底层实际上new了一个HashMap集合.向HashSet集合中存储元素,实际上是存储到HashMap集合中去了,HashMap是一个哈希表数据结构

JDK8新特性:钻石表达式 List list = new ArrayList<>();类型自动推断

5、HashMap和Hashtable的区别。
HashMap: 初始化容量16,扩容2倍。非线程安全,key和value可以为null。默认因子 .75
Hashtable:初始化容量11,扩容2倍+1,线程安全,key和value都不能是null。

正则表达式语法中
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配字母、数字、下划线。等价于’[A-Za-z0-9_]’。
\W 匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。

java8中,ThreadLocal类用到了解决哈希冲突的开放定址法

HttpSessionAttributeListener:可以实现此侦听器接口获取此web应用程序中会话属性列表更改的通知。
HttpSessionBindingListener:当该对象从一个会话中被绑定或者解绑时通知该对象,这个对象由HttpSessionBindingEvent对象通知。这可能是servlet程序显式地从会话中解绑定属性的结果,可能是由于会话无效,也可能是由于会话超时。
HttpSessionObjectListener:没有该接口API。
HttpSessionListener:当web应用程序中的活动会话列表发生更改时通知该接口的实现类,为了接收该通知事件,必须在web应用程序的部署描述符中配置实现类。
HttpSessionActivationListener:绑定到会话的对象可以侦听容器事件,通知它们会话将被钝化,会话将被激活。需要一个在虚拟机之间迁移会话或持久会话的容器来通知所有绑定到实现该接口会话的属性。

抽象类中的抽象方法(其前有 abstract1修饰)不能用 private、 static、 synchronized、native访回修饰符修饰。原因如下:
1、private
抽象方法没有方法体,是用来被继承的,所以不能用 private修饰。
2、static
static修饰的方法可以通过类名来访间该方法(即该方法的方法体),抽象方法用sttic修饰没有意义。
3.、synchronized
该关键字是为该方法加一个锁。而如果该关键字修饰的方法是 static方法。则使用的锁就是class变量的锁。如果是修饰类方法。则用this变量锁。
但是抽象类不能实例化对象,因为该方法不是在该抽象类中实现的。是在其子类实现的。所以,锁应该归其子类所有。所以,抽象方法也就不能用 synchronized关键字修饰了。
4、native
native这个东西本身就和 abstract冲突,他们都是方法的声明,只是一个把方法实现移交给子类,另一个是移交给本地操作系统。如果同时出现,就相当于即把实现移交给子类,又把实现移交给本地操作系统,那到底谁来实现具体方法呢?
接口是一种特殊的抽象类,接口中的方法全部是抽象方法(但其前的 abstract可以省略),所以抽象类中的抽象方法不能用的访间修饰符这里也不能用。同时额外说明一下protect关键词
5、protect
protected访同修饰符也不能使用,因为接口可以让所有的类去实现(非继承),不只是其子类,但是要用public去修饰。接口可以去继承一个已有的接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值