JavaSE高级篇学习笔记,javase学习笔记
JavaSE高级篇学习笔记,javase学习笔记
基本数据类型的封装类
1.byte Byte
char Character
short Short
int Integer
long Long
folat Float
double Double
boolean Boolean
2.自动装箱与拆箱
装箱:把基本数据类型转化为封装类型
拆箱:把封装类型转化为基本数据类型
拆箱示例:
Integer i1 = new Integer(10);
int i2=i1;
装箱示例:
int i3=9;
Integer i4=i3;
Object类介绍
1.Object类的常用方法
在java中所有的类都继承自Object类。
1、一个类的实例化对象,要想使用使用clone()方法,就必须让这个类实现Cloneable接口,然后重写clone()方法。
2、System.gc();//建议虚拟机执行垃圾回收,但不保证执行,也不保证回收所有垃圾。
3、finalize()和gc()这两个方法我们不要试图去控制,他们是由Java虚拟机控制的,我们只有建议gc()去执行finalize(),但具体是否执行,只有Java虚拟机才知道。因为这是由Java虚拟机的算法决定的。
Math类
Math类里面都是静态方法。
1、Math类介绍:
double d=Math.celi(2.98);
System.out.println(d);
输出结果是3 (向上取整)
d=Math.floor(2.98);
System.out.println(d);
输出结果是2 (向下取整)
Math.Radom() [0,1)
2、猜数字小游戏
猜数字小程序优化,增加次数限制的功能。
StringBuffer类
1、StringBuffer类简介
String容量是不可变的,每次使用String时候都产生一个对象,所以可以产生大量的垃圾。而StringBuffer类容量是可变的,它是带缓存的。
StringBuffer sb =new StringBuffer();
System.out.println(sb.capacity());
StringBuffer sb2=new StringBuffer("abcd");
System.out.println(sb2.capacity());
StringBuffer sb3=new StringBuffer(100);
System.out.println(sb3.capacity());
2、StringBuffer类的方法
线程安全的。
Date类
1、Data类
2、格式化时间类DateFormate类
它是个抽象类,不能直接通过构造方法new出对象
可以通过以下两种方式间接获取:
//通过抽象类的静态方法获取实例
DateFormat df1=DateFormat.getInstance();
//通过new 子类获得实例
DateFormat df2=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
示例:
public class TestDateFormate {
public static void main(String[] args) {
Date dt=new Date();
//通过抽象类的静态方法获取实例
DateFormat df1=DateFormat.getInstance();
//通过new 子类获得实例
DateFormat df2=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
DateFormat df3=new SimpleDateFormat("yyyy年MM月dd号 hh点mm分ss秒");
DateFormat df4=new SimpleDateFormat("yyyy-MM-dd");
System.out.println(dt);
System.out.println("1.通过抽象类的静态方法获取实例\n" +df1.format(dt));
System.out.println("2.yyyy-MM-dd hh:mm:ss\n" +df2.format(dt));
System.out.println("3.yyyy年MM月dd号 hh点mm分ss秒\n" +df3.format(dt));
System.out.println("4.yyyy-MM-dd\n" +df4.format(dt));
}
}
输出结果:
Sat Aug 20 11:15:31 CST 2016
1.通过抽象类的静态方法获取实例
16-8-20 上午11:15
2.yyyy-MM-dd hh:mm:ss
2016-08-20 11:15:31
3.yyyy年MM月dd号 hh点mm分ss秒
2016年08月20号 11点15分31秒
4.yyyy-MM-dd
2016-08-20
初识I/O流
流的概念
读入,写出。
输入流是读数据。
输出流是写数据。
输入输出的概念是针对程序来说的。程序往资源文件里输入,相对资源文件来说是资源文件再读程序。而程序的输出,就是资源文件在返回请求,写数据给程序。
1、字节流
用于以字节为单位的输入输出。只要是处理字节或者二进制的各种输入输出。一般是用于处理图像,声音等(文件)。
InputStream是所有文字输入流的祖先类。
OutputStream是所有字节输出流的祖先类。
2、字符流
以字符为基本处理的单位,主要用于处理字符或者是文本类型。一般用作处理文本的读取存储以及与网络的(文本)信息的交互。
Reader 是所有字符输入流的祖先类。
Writer 是所有字符输出流的祖先类。
3、文件管理
读文件 输入流
写文件 输出流
文件字节输入流
InputStream
1.FileInputStream
因为字节流每次读取一个字节,而一个字节是无法完整的描述一个中文的。所以会出现英文正常,中文乱码的情况。
public class TestFileInputStream {
public static void main(String[] args) {
FileInputStream fis=null;
int i=0;
try {
fis=new FileInputStream("E:\\个人信息\\fuben.txt");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
i=fis.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//当i=-1时,文件到达结尾
while(i!=-1){
System.out.print((char)i);
try {
i=fis.read();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
文件字节输出流
FileOutputStream
public class TestFileOutputStream {
public static void main(String[] args) {
String s=”woainiwangdanwoyaonulizhaodaogoodjoobformybeau”;
FileOutputStream fos=null;
FileOutputStream fos1=null;
File f=new File("E:\\个人信息\\f.txt");
File f1=new File("E:\\个人信息\\f1.txt");
if(!f.exists()){
try {
f.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(!f1.exists()){
try {
f1.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
try {
fos=new FileOutputStream(f);
fos1=new FileOutputStream(f1);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] b=s.getBytes();
try {
fos.write(b);
fos1.write(b, 0, s.length()/2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
if(fos!=null){
fos.close();
}
if(fos1!=null){
fos1.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字节流相关的类:字节数组输入流
ByteArrayInputStream
FileInputStream的输入源是文件
ByteArrayInputStream的输入源是字节数组
rest()重置到mark标记的位置,如果没有调用过mark方法,则重置到缓冲区ay(BateArray)的起始位置
mark(int)
public class TestByteArrayInputStream {
public static void main(String[] args) throws IOException {
String temp="abcdefghijklmnopqrstuvwxyz";
byte[] b=temp.getBytes();
ByteArrayInputStream bis =new ByteArrayInputStream(b);
for(int i=0;i<2;i++){
int c=0;
c=bis.read();
while(c!=-1){
if(i==0){
System.out.print((char)c);
}else{
System.out.print(Character.
toUpperCase((char)c));
}
c=bis.read();
}
System.out.println();
bis.reset();
}
}
}
输出流字节数组
1.ByteArrayOutputStream
FileoutputStream把文件作为写入的目的地(写入到硬盘)
ByteArrayOutputStream 把字节数组作为写入的目的地(写入到内存里)
public class TestByteArrayOutputStream {
public static void main(String[] args) {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
String temp="hello world hello everyone";
byte[] b=temp.getBytes();
try {
bos.write(b);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(bos.toString());
//写入到 byte[] buf=new byte[size]
byte[] b1=bos.toByteArray();
for(int i=0;i<b1.length;i++){
System.out.print((char)b1[i]);
}
}
}
字节流相关类:缓冲输入输出字节流
1、BufferedInputStream
2、BufferedOutputStream
GBK -中文占2个字节
UTF-8中文占3个字节
测试编码方式的方法:System.out.println(System.getProperty(“file.encoding”));
结果:GBK
测试一个汉字占多少个字节的方法:System.out.println(“大家好”.getBytes().length); 结果:6 所以说一个汉字在GBK编码方式下,占2个字节。
字符流的输入祖先都:Reader
字符流相关类:字符输入流
InputStreamReader 字节流通往字符流的桥梁
public class TestInputStreamReader {
public static void main(String[] args) {
FileInputStream fis =null;
InputStreamReader isr=null;
try {
fis=new FileInputStream("E:\\个人信息\\in.txt");
isr=new InputStreamReader(fis);
int c=0;
c=isr.read();
while(c!=-1){
System.out.print((char)c);
c=isr.read();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
try {
if(fis!=null){
fis.close();
}
if(isr!=null){
isr.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字符流相关类:字符输出流
字符流的输出的祖先都是:Writer
OutputStrmWriter 字符到字节的桥梁(通过编码方式进行转换)
public class TestOutputStreamWriter {
public static void main(String[] args) {
FileOutputStream fos=null;
OutputStreamWriter osw=null;
String s=null;
try {
fos=new FileOutputStream("E://个人信息//out.txt");
osw=new OutputStreamWriter(fos);
s="你好,我喜欢学习新技术. i like new technology!";
for(int i=0;i<s.length();i++){
osw.write(s.charAt(i));
}
osw.flush();//手动刷新很重要
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//关闭流
if(fos!=null){
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(osw!=null){
try {
osw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
字符流相关类:读文件类
1、FileReader
public class TestFileReader {
public static void main(String[] args) {
FileReader fr=null;
try {
fr=new FileReader("E:\\个人信息\\in.txt");
int c=0;
c=fr.read();
while(c!=-1){
System.out.print((char)c);
c=fr.read();
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(fr!=null){
try {
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
字符流相关类:写文件类
1、FileWriter
public class TestFileWriter {
public static void main(String[] args) {
FileWriter fw=null;
try {
fw=new FileWriter("E:\\个人信息\\out.txt");
String str="你好,we come from new world!";
for(int i=0;i<str.length();i++){
fw.write(str.charAt(i));
}
fw.flush();//最好是手动调用,从内存到文件。
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(fw!=null){
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
对象序列化
作用:
对象持久化,比如保存到硬盘的文件。
在网络中进行传输。
1.Serializable接口
2.对象输入/输出流
ObjectInputStream
(Student)ois.readObject()
(Teacher)oos.writeObject;
ObjectOutputStream
oos.writeObject(Student);
oos.writeObject(Teacher);
写几个就要读几个,还要注意的是在读的时候注意强转类型。
3.transient关键字
被它修饰的字段是无法进行序列化的,也就是没有写进文件,所以也就无法读取。(将不需要写进文件的东西进行保护)
泛型概念
作用:提高类型的安全并能简化类型转换的过程。
1.什么是泛型
1、泛型是JDK5.0新添加的特性
2、泛型就是将类型参数化
3、提高类型的安全并能简化类型转换的过程。在泛型处理过程中,所有的类型转换都是自动和隐式的。
泛型将类型的错误提前到了编译期。
2.没有泛型的情况
数据类型转换比较复杂。
Integer i2=(Integer)g1.getObject();
String s2=(String)g2.getObject();
在转换过程中会产生不安全的因素。
泛型的基本写法
泛型就是将类型参数化
泛型处理的必须是类的类型,不能用它来处理int,long等基本类型。
多个类型参数
1.使用两个或者多个类型参数
public class TwoGen
}
泛型的类型边界
1.类型边界
public class Average {
T[] ts;
public Average(T[] obj) {
this.ts=obj;
}
public int Average(){
double sum;
for(int i=0;i
}
泛型通配符的使用
类型边界的作用:
1、可以获得类型安全。
2、可以让类型有进一步的操作能力。
1.通配符的使用
通配符 ?代表参数可以使任何的Average对象
public boolean equalsAvg(Average<?> obj){
if(this.average()==obj.average()){
return true;
}else {
return false;
}
}
泛型方法
Gen{
}
1、泛型方法
在非泛型类中也可以有泛型方法。
2、定义泛型方法的格式:
修饰符 方法类型 <参数类型列表> 返回值类型 方法名(参数列表){
}
示例:
public static boolean have(T[] ts, T t) {
}
泛型类之间的继承
1、泛型类之间的继承
GenChildextends GenParent
定义泛型子类,声明中必须包含其父类的类型参数。即便在子类中不使用任然要在参数列表中指定它。
泛型类与非泛型类之间的继承
1、泛型类与非泛型类之间的继承
父类是泛型类,子类不是泛型类(不成立)
如果子类继承了泛型父类,则子类必须得是泛型类,并且包 父类的泛型。
父类不是泛型类,子类是泛型类,正常写就可以了,没有强制性的要求
public class GenChild<T> extends Parent
泛型继承中方法覆盖
1、方法覆盖
对于泛型类的继承来说,方法覆盖同样适用!
集合框架概述
1.什么是集合框架
java的集合框架是java.util包中提供的一系列工具,它为程序处理对象组提供了标准的方式。诞生自1.2版本。
1.2版本之前,我们如何处理对象组?
1、数组
缺点:长度固定,数组中只能存放一种类型的数据。
2、Vector、Stack、Properties
缺点:缺乏统一的操作方式。不易扩展。
1.2版本之后,诞生了集合框架
优点:性能提高了。
操作统一。Collection List Set
提高了扩展性。
集合实现了Iterator接口。
迭代器:提供了访问接口的统一方法。
集合存储的是一组单个的数据。
Map存储的是一组成对的数据。
2.常用接口以及实现类介绍
常用接口 Set、List、Queue
1.Set实现类:HashSet、LinkedHashSet、TreeSet
2.List实现类:ArryList、Vector、LinkedList
3.Queue实现类:LinkedList、PriorityQueue
Collection是所有集合的父接口,不包含Map
Set继承自Collection,不允许出现相同的元素。
List 继承自Collection .以列表形式存储的集合。
集合实现类ArrayList
1.ArrayList
数组列表。它可以自动扩容。
public class TestArrayList {
public static void main(String[] args) {
ArrayList<String> all = new ArrayList<String>();
all.add("a");
all.add("b");
all.add("c");
all.add("d");
System.out.println("all的长度是:" + all.size());
System.out.println("all的内容" + all);
// 增加的方法
System.out.println("把第一个元素设置为first");
all.add(0, "first");
System.out.println("all的内容" + all);
all.add("e");
// 修改的方法
System.out.println("把b改为B");
all.set(2, "B");
System.out.println("修改后all的内容" + all);
// 删除方法
System.out.println("删除d元素");
all.remove("d");
System.out.println("删除d后all的内容" + all);
System.out.println("删除e元素");
all.remove(4);
System.out.println("删除e后all的内容" + all);
// 查询方法
for (String s : all) {
System.out.print(s + " ");
}
System.out.println();
for (int i = 0; i < all.size(); i++) {
System.out.print(all.get(i) + " ");
}
System.out.println();
System.out.println("打印s1数组");
// ArrayList和数组的交互
String[] s1 = new String[all.size()];
s1 = all.toArray(s1);
for (String s : s1) {
System.out.print(s + " ");
}
System.out.println();
ArrayList<String> all2=new ArrayList<String>(all);
System.out.println("打印all2的内容"+all2);
//在构造的时候指定容量
System.out.println();
ArrayList<String> all3=new ArrayList<String>(3);
all3.addAll(all);
System.out.println("all3的内容:"+all3);
}
}
list实现类:LinkedList
public class TestLinkedList {
public static void main(String[] args) {
LinkedList<String> lel = new LinkedList<String>();
// add方法
lel.add("a");
lel.add("b");
lel.add("c");
lel.add("d");
lel.add("e");
System.out.println(lel);
//在尾部增加元素
lel.addLast("f");
System.out.println(lel);
//在头部增加元素
lel.addFirst("first");
System.out.println(lel);
lel.add(7, "last");
System.out.println(lel);
String s=lel.poll();
System.out.println("poll操作后获取的内容:"+s);
System.out.println("poll操作后lel的内容:"+lel);
s=lel.peek();
System.out.println("peek操作后获取的内容:"+s);
s=lel.pop();
System.out.println("pop操作后获取的内容:"+s);
System.out.println(lel);
String[] ss=new String[lel.size()];
lel.toArray(ss);
for(String s1:ss){
System.out.print(s1+" ");
}
//有参的构造方法
LinkedList<String> lel2=new LinkedList<String>(lel);
System.out.println();
System.out.println(lel2);
}
}
Set实现类:HashSet
它是通过散列的机制来进行存储到哈希表。它的存取速度非常快,但是不能该保证集合的顺序,它里面没有重复的值。它存取机制是通过hashcode来取余,来快速计算出它的下标,从而找到存取位置。
实现自己的ArryList
ArrayList的容量可以动态增加
底层数据结构是数组
增、删、改、查
boolean add(Object obj)
Object remove(int index)
Object set(int index,Object obj)
Object get(int index)
toString()
迭代器介绍
1、迭代器介绍
迭代器是用来遍历集合中的元素的,通过使用迭代器,可以将遍历与数据分离。
2、迭代器的使用
通过Iterator对象来遍历集合中的元素的对象。
public static void bianli(Iterator it) {
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
}
3、for-each
1、通用,适用于所有的集合
2、简便,语法格式简单
for (String s : list) {
System.out.print(s+" ");
}
Map接口介绍与实现类HasMap
1、Map接口介绍
map(key,value)
key必须唯一,value不是必须唯一。
2、实现类HasMap
public class TestHashMap {
public static void main(String[] args) {
HashMap<Integer, String> hm = new HashMap<Integer, String>();
hm.put(101, "老王");
hm.put(102, "小明");
hm.put(103, "小花");
hm.put(104, "小李");
Collection<String> c = hm.values();
Iterator<String> it = c.iterator();
System.out.println("姓名列表");
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
System.out.println();
System.out.println("学号列表");
Set<Integer> keys = hm.keySet();
for (Integer i : keys) {
System.out.print(i + " ");
}
System.out.println();
System.out.println("打印完整信息");
for (Integer key : keys) {
System.out.print("学号:" + key + ",姓名:" + hm.get(key) + "/");
}
}
}
Map实现类TreeMap
1、TreeMap
通过树结构来实现Map接口的。
TreeMap保证了映射按照升序顺序排列key
支持快速查找
由于TreeMap会对key进行排序的,所以我们必须保证所传的key是能够进行排序的。
如何把普通的类变成可排序的类:
实现comparable接口,重写compareTo(Object obj)方法。
List
ArrayList 查询多,增加删除比较少(底层是数组)
LinkedList 增加删除比较多,查询
如果涉及到堆栈,队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList。
如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。
要特别注意对哈希表的操作,作为key的对象要正确复写equals和hashCode方法。
尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码不用改变。这就是针对抽象编程。
网络编程之InteAddress
主机名(域名)到 IP 地址的解析 通过使用本地机器配置信息和网络命名服务(如域名系统(Domain Name System,DNS)和网络信息服务(Network Information Service,NIS))来实现。要使用的特定命名服务默认情况下是本地机器配置的那个。对于任何主机名称,都返回其相应的 IP 地址。
反向名称解析 意味着对于任何 IP 地址,都返回与 IP 地址关联的主机。
InetAddress 类提供将主机名解析为其 IP 地址(或反之)的方法。
1、InetAddres:表示网络协议地址的类,可以用于标记网络上的硬件资源(比如主机)
public class TestInetAddress {
public static void main(String[] args) {
try {
InetAddress ia = InetAddress.getByName("www.baidu.com");
System.out.println(ia);
System.out.println("------------------------------------");
InetAddress[] a = InetAddress.getAllByName("www.baidu.com");
for (InetAddress i : a) {
System.out.println(i);
}
InetAddress address = InetAddress.getLocalHost();
System.out.println(address);
System.out.println("====================");
byte[] bs = new byte[] { (byte) 180, 97, 33,107 };
InetAddress ip = InetAddress.getByAddress(bs);
System.out.println(ip);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
网络编程之URL类:(主机当中存放得具体资源)
1、URL:统一资源定位符(Uniform Resource Locator),它表示Internet上某一资源的地址。
InetAddres:硬件资源地址(主机)
public class UrlReader {
public static void main(String[] args) {
try {
URL url = new URL("http://www.taoche.com/all/?WT.mc_id=tc114lam");
InputStreamReader isr = new InputStreamReader(url.openStream());
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
isr.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Socket通信过程理论分析:
1、ServerSocket类
//创建服务端程序
ServerSocket server=new ServerSocket(1995);0-65535
Socket s=server.accept();
通过s获得输入输出流,与客户端进行交互
2、Socket类
Socket socket=new Socket(“127.0.0.1”,1995);
通过socket获得输入输出流,与服务器进行交互
3、通信过程
public class Server {
public static List<Socket> sockets = new ArrayList<Socket>();
public static List<String> names = new ArrayList<String>();
public static void main(String[] args) {
try {
names.add("笨笨熊");
names.add("喜洋洋");
names.add("小灰灰");
names.add("红太狼");
names.add("光头强");
System.out.println("服务器启动!");
ServerSocket server = new ServerSocket(1995);
int count = 0;
while (true) {
System.out.println("等待客户端连接!");
Socket s = server.accept();// 等待客户端的连接
sockets.add(s);
System.out.println("客户端已经连接,目前在线人数:" + sockets.size() + "!");
new SocketThread(s, names.get(count++)).start();
// 服务器为每一个客户端连接分配线程
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class SocketThread extends Thread {
private Socket s;
private String name;
public SocketThread(Socket socket, String name) {
this.s = socket;
this.name = name;
}
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String content = null;
while (true) {
content = br.readLine();// 阻塞状态,等待客户端发来消息
for (Socket socket : Server.sockets) {
OutputStreamWriter osw = new OutputStreamWriter(socket.getOutputStream());
osw.write(name + ":" + content + "\n");
osw.flush();
}
System.out.println("日志记录:"+name + ":" + content);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1", 1995);
new SendTread(s).start();
new GetThread(s).start();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 发送消息的线程
class SendTread extends Thread {
private Socket s;
public SendTread(Socket s) {
this.s = s;
}
public void run() {
try {
OutputStreamWriter osw = new OutputStreamWriter(s.getOutputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String content = br.readLine();//阻塞状态,是让客户端从键盘输入消息
osw.write(content + "\n");
osw.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 接收消息的线程
class GetThread extends Thread {
private Socket s;
public GetThread(Socket s) {
this.s = s;
}
public void run() {
try {
while (true) {
System.out.println("客户端启动!");
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String content = br.readLine();//阻塞状态,接服务端发来的消息
System.out.println(content);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
相关文章
- 暂无相关文章
用户点评