什么是UML:

用来写类和对象和方法的关系的图

power designer工具介绍

做界面的,有各种组件

java中的空白:

/t

/n

/r

编译器针对于空白的处理:忽略多余的空白

注释:

单行注释://;ctrl+/

多行注释:ctrl+shift+/

文档注释:/** <注释内容> **/

语句:

最小单位是“;”

快语句:花括号里的

关键字:

有特殊用途的单词;

标识符

给各种方法,变量,类起名字时候用到的

命名规则:

前提:不能使用关键字

开头:[字母]或者[下划线]或者[$]符号

整体:[字母],[下划线],或[$]或者[数字],数字不能放最前面

约定俗成的定义方法:见名知意:小驼峰,大驼峰等等。

常量

定义

使用规范:

1.final修饰

声明的时候必须初始化;

程序执行过程:

JVM执行过程

课后作业1

检查代码错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Test006 {
public static void main(String[] ages){
final int PI;
double a=6;
int b=7.7;//整形变量不能有小数
int c=8;
9=c;//变量定义语句错误
c=c+1;
int d =c+e;//没有提前定义e
System.out.println(d);

}

}

修改后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Test006 {
public static void main(String[] ages){
final int PI;
double a=6;
int b=7;//整形变量不能有小数
int c=8;
c=9;//变量定义语句错误
c=c+1;
int e=0;
int d =c+e;//没有提前定义e
System.out.println(d);

}

}

数据类型:

1.布尔类型:

False

true

2.整形:

byte一个字节;short2个字节;int4个字节;long8个字节(后面加个L)

运算符:

类型转换说明

自动类型转换:

当操作数类型不同时,按高级别类型进行运算

基本类;型级别从低到高:byte→short→int→long→float→double

自动类型提升:

byte/short/char运算时自动提升为int

移位结果可能超出原类型范围

强制转型风险:

高位截断:只保留最低8位(byte类型)

示例说明:536870911强制转为byte得-1

解决方案:使用更大数据类型存储移位结果

特殊注意事项:

负数逻辑右移后可能变为极大正数

连续移位需注意中间结果的类型转换

建议使用int/long类型进行移位运算

位运算****:

基本类型:包括按位与(&)、按位或(|)、按位取反(~)和按位异或(^)四种运算符

运算对象:对整数的二进制形式逐位进行运算

三元运算

条件表达式 ? 表达式1 : 表达式2

当问号前的条件表达式为真时,返回冒号前的表达式1;为假时返回冒号后的表达式2

instanceof运算符

功能作用:判断对象是否属于特定类的实例

语法格式:对象 instanceof 类名

使用示例:

执行结果:输出”s1是Student类的实例”,因为s1确实是通过Student类实例化的对象

类模板关系:即使类定义很简单(如示例中仅包含age属性和walk方法),只要对象由该类创建,instanceof判断即为真

类型转换:

触发条件:当变量或值赋值给另一个变量时,若数据类型不同则需类型转换

类型等级:从低到高依次为

byte>short>char>int>long>float>double

自动转换:

当低等级给高等级的时候会进行自动字符转换

且不造成数据精度的损失

强制转换:

必须整体转换表达式,如(float)(a + b)而非(float)a + b

精度风险:高等级转低等级可能导致数据溢出或精度损失

//布尔类型不可与其他类型相互转换

表达式语句,块,分支语句

表达式语句

块:花括号里面的复合语句当作一条语句来看待

分支语句:if else

Switch case

case后面必须加break;要不然会执行下面的case(case穿透)

default分支是switch中case全没有命中的情况下的失败处理

循环语句:

for:for(表达式1;表达式2;表达式3){语句}

for循环语句中三个表达式都可以省略(但是分号不能省略)

break语句:立即终止整个循环

continue语句:跳过本次循环剩余语句直接执行表达式3;

for循环语句对于数组的特殊写法:

for(int i:arr1){

System.out.println(i);

}

无限循环写法:

1
for(;;){....}

While:

1
while(布尔表达式){循环体;}

当表达式是true的时候执行循环体

当false时结束循环

do–while:

  1. 1.无条件执行一次循环体

  2. 2.计算布尔表达式值

  3. 3.若为true则重复执行循环体

  4. 4.直到表达式为false时退出循环

类的定义格式:

桌面窗口台球:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//台球碰撞
import java.awt.*;
public class MyFrame {
private int selfwidth=500,selfHighth =300;
private int x=200,y=300;
private int screenWidth=0,screenHighth=0;
private int loopCount;
private boolean flagX=true,flagY=true;
private Frame frame;

public void creatwindows(){
//创建一个窗口
frame = new Frame("台球窗口");
//窗口可见性
frame.setVisible(true);
//设置窗口的大小
frame.setSize(selfwidth,selfHighth);
frame.setBackground(new Color(255,0,0));
//窗口位置
frame.setLocation(x,y);
//设置窗口大小是否可以改变
frame.setResizable(false);

Dimension screenSize =Toolkit.getDefaultToolkit().getScreenSize();
screenWidth=screenSize.width;
screenHighth=screenSize.height;

}
public void walk(){
while(true){
loopCount+=1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//根据变化方向改变x和y的值
if (flagX)
x+=1;
else
x-=1;
if (flagY)
y+=1;
else
y-=1;
//判断碰撞
if(x<0||(x+selfwidth)>screenWidth)
flagX=!flagX;
if (y<0||y+selfHighth>screenHighth)
flagY=!flagY;


frame.setLocation(x,y);

}
}

}

对象的创建和初始化

对上一个模块的代码进行提取变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//台球碰撞
import java.awt.*;
public class MyFrame {
private int selfwidth=500,selfHighth =300;
private int x=200,y=300;
private int screenWidth=0,screenHighth=0;
private int loopCount;
private boolean flagX=true,flagY=true;
private Frame frame;

public void setWindowsSize(int pWindowsWide,int pWindowsHeigth){
selfwidth=pWindowsHeigth;
selfHighth=pWindowsHeigth;
}
public void setPos(int px,int py){
x=px;
y=py;
}
public void setFlag(boolean pflagX,boolean pflagY){
flagX=pflagX;
flagY=pflagY;
}
public void creatwindows(){
//创建一个窗口
frame = new Frame("台球窗口");
//窗口可见性
frame.setVisible(true);
//设置窗口的大小
frame.setSize(selfwidth,selfHighth);
frame.setBackground(new Color(0, 255, 225));
//窗口位置
frame.setLocation(x,y);
//设置窗口大小是否可以改变
frame.setResizable(false);

Dimension screenSize =Toolkit.getDefaultToolkit().getScreenSize();
screenWidth=screenSize.width;
screenHighth=screenSize.height;

}
public void walk(){
while(true){
loopCount+=1;
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//根据变化方向改变x和y的值
if (flagX)
x+=1;
else
x-=1;
if (flagY)
y+=1;
else
y-=1;
//判断碰撞
if(x<0||(x+selfwidth)>screenWidth)
flagX=!flagX;
if (y<0||y+selfHighth>screenHighth)
flagY=!flagY;


frame.setLocation(x,y);

}
}

}

构造方法以及重载

构造方法:

核心作用: 在实例化对象(new操作)时被调用,主要用于初始化成员变量

分类类型: 分为有参构造和无参构造两种形式

默认行为: 当类中没有显式定义构造方法时,系统会自动生成无参构造方法

1
2
3
4
5
6
//构造方法的格式
public class 类名{
修饰符 类名([参数列表]){
方法体
}
}

特征:

命名要求: 必须与类名完全相同,采用大驼峰命名法

返回值限制: 不能有任何返回类型声明(包括void)

访问权限: 必须为public,private会导致实例化失败

默认覆盖: 当定义有参构造后,系统不再提供默认无参构造

方法重载

基本概念: 同一类中多个方法名相同但参数列表不同

参数差异: 可通过参数类型、数量或顺序区分

无关因素: 与返回值类型和访问修饰符无关

类内限定: 必须在同一个类中实现

同名要求: 方法名称必须完全相同

参数区分: 通过参数列表差异识别(类型/数量/顺序)

灵活优势: 提供方法的多版本实现,增强代码可读性

调用机制: 编译器根据传入参数自动匹配对应方法

类的继承的定义

关键字:使用extends表示扩展关系,写在子类类名之后。

访问权限控制:private,default,protected,public

img

包这个地方可以说是同一个目录下

继承

有就用自己的,没有就用父类的

都有就要用:super(代☞父类),this(代指自己的),final(最终结果了不再更改);

四个权限:pribate(私有的)只能同一个包同一类中用;

default(默认的)同一个包中的不同类

protected不同包的子类可以访问

public(随便访问)

多态(为了代码重用)

重写父类的方法

这里区分重载:重载是方法名相同但是参数不同或者返回值不同

对象转换

1.向上转型:

1
Animal cat1 = new Cat();

这种是父类引用但是真实对象是Cat子类;不用强制转换

只能用父类有的方法和属性,但是具体的方法和属性的运行的代码逻辑是子类里重写过的父类方法(要是没有那就直接引用父类的方法)

2.向下转型

语句是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Animal cat1 = new cat();
Cat cat2 =(Cat) cat1 //这个地方没有调用构造函数也就是没有新的对象产生都是cat1只不过标签不同将cat1用cat2来赋值
//也就是cat1和cat2本质是一个对象。只不过cat1是父类引用,cat2改为了子类引用
//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {
public static void main(String[] args) {
// Cat cat1 =new Cat();
// cat1.Name="小黄";
// cat1.eat();
// Cat cat2 =new Cat();
// cat2.MyAge=3;
// Animal a1=new Animal();
// a1.eat();
Dog dog1=new Dog();
dog1.eat();//纯dog

Animal dog2=new Dog();
dog2.eat();//dog2向上转换为Animal引用

Dog dog3 =(Dog) dog2;
dog3.eat();//将向上转换的dog2转为DOg引用

Animal dog4 =new Animal();
Dog dog5 =(Dog) dog4;
//将纯Animal向下强制转换为Dog//但是父类强转不了成为子类所以报错
dog5.eat();
}
}

最后一种方法的报错是:类型转换异常:Animal 类 无法被强制转换成 Dog 类,Animal 和 Dog 都在应用类加载器的未命名模块中

img

关键字:

1.static(静态的):可以修饰成员变量,方法和方法块;

修饰属性:被static修饰的属性所有对象共享同一个值

这些属性会被保存在内存的方法区中

可以节省内存资源

静态属性(类属性)使用类名调用

修饰方法:被称为静态方法(类方法)

静态方法可以直接使用类名调用,无需实例化对象

静态方法中无法调用普通的属性和方法,因为静态方法中没有this

如果一个不需要访问当前类中的实例成员就可以定义静态的

静态方法不能被重写

修饰代码块

1
2
3
static {
................
}

在类加载的时候就执行一次

生命周期和类是一样长的

2.abstract(抽象的):可以修饰方法和类

修饰方法:被称为抽象方法;//只有方法定义没有方法实现;用一个分号结尾

类中有抽象方法那类也必须定义为抽象类

继承抽象类时候必须重写抽象类中的抽象方法

final关键字和abstract关键字是冲突的;

方法重写规则和包装规则:

方法重写:

总述:

子类重写父类中的方法;

规则:方法名和形参必须要有完全相同的签名返回类型也必须一致.//返回类型可以是子类型

子类重写可以改变其访问权限.

子类重写的方法不能抛出比父类中被重写的方法更广泛的异常.

static方法可以被重写

子类方法中可以调用父类中的源方法:用super关键字;

包装类型:

将数据类型包装成类;(更好的使用这个后面再看)

接口:

关键字:interface

接口其实就是一个完全的抽象类里面的所有方法全是抽象方法;抽象到极致

接口的实现是用的implements关键字

接口可以实现多个类

作用:一个提纲算是;

可以一次性实现多个接口;

内部类:

类里面再声明一个类就叫内部类

//静态方法(尤其是main函数)不能直接new内部类;

内部类可以无限制访问外部类;反过来外部类访问内部类需要先建立一个成员内部类的对象

一.成员内部类(最普通的)(非静态的)(先外后内)

依附于外部类对象,先创建外部类实例再创建内部类实例

能直接访问外部类的所有成员

不能定义static静态成员

属于对象级别

先外后内

1
2
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();

内部类只为外部类服务

*二.静态内部类(static成员内部类)(直接内)*

对比成员内部类多加了一个static;

属于外部类本身,不能访问外部非静态成员;只能访问静态

可以写静态/普通方法

独立性最高

1
Outer.Inner inner = new Outer.Inner();

三.局部内部类(方法里写的类)

定义在方法或者代码块中的;

作用域仅限于当前方法,外面用不了

能访问方法里的final/常量变量

使用场景:临时用的时候

四.匿名内部类(无名字,最常用)

没有类名,一次性使用

直接new接口和抽象类/普通类并重写方法

不能写构造方法

使用场景:线程创建的时候

接口的快速实现

事件监听

回调函数,简易抽象类的实现

快速补全抽象方法

匿名类:

没有名字的内部类(实现接口,抽象类的快速重写,对普通方法的重写)直接new

接口的快速实现

事件监听

回调函数,简易抽象类的实现

快速补全抽象方法

PS:抽象类和接口的区别;

抽象类abstract class半完成****父类,有普通成员、构造

接口interface行为规范 / 标准,只定规则

对比 抽象类 接口
关键字 abstract class interface
构造方法 没有
成员变量 普通变量、常量都能写 只能常量(默认 public static final)
成员方法 抽象方法 + 普通实例方法 JDK7 只有抽象方法;8 + 有默认 / 静态
继承数量 单继承,只能 extends 一个 多实现,可 implements 多个
权限 四种权限都能用 默认public
设计思想 是什么(本质) 能做什么(行为)
使用 extends 继承 implements 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Main {
public static void main(String[] args) {
// Farm farm1=new Farm("x",23);
// Farm.Cow cow =farm1.new Cow("mu1",23);
Farm.Cow cow = new Farm.Cow("我是牛",26);
cow.speak();
new cry(){
@Override
public void Cry() {
System.out.println("wuwuwu");//对接口
}
}.Cry();
new cry(){
@Override
public void Cry() {
System.out.println("fuck");//对接口
}
}.Cry();
new Animal(){
@Override
public void fuck() {
System.out.println("oh yes");//对抽象类
}
}.fuck();
new Person(){
@Override
public void show() {
System.out.println(Person.y);//对普通方法
}
}.show();
}
}

数组初始化与使用:

数组声明与定义:其实和变量差不多

1
int [] a;

初始化://静态初始化和动态初始化不要一起使用;定义和初始化一定在一起

1.静态初始化:

1
2
int[] arr1 ={1,2,3}
int[] arr3 = new int[]{1,2,3,4}

2.动态初始化

1
int[] arr2 = new int[arrlenth]

浅拷贝:两个数组指针指向同一个内存地址

1
2
int[] arr1 =new int[]{1,2,3};
int[] arr2 =arr1;

深拷贝:开辟两个内存空间两个内存空间的内容相同

1
2
3
4
5
6
7
8
9
int[] arr1 =new int[]{1,2,3};
int[] arr2 =new int[arr1.length];
for(i=0;i<=2;i++){
arr2[i]=arr1[i];
}

//用系统的方法
int[] arr3 = new arr[]{13,30,32,54,57,69};
System.arraycopy(arr1,0,arr2,0);

排序:

1
Arrays.sort(arr);

多维数组:

1
2
3
4
5
6
7
8
9
10
11
int[][] arr8 =new int[4][];
arr8[0]=new int[3];
arr8[1]=new int[]{1,1,1,1};
arr8[2]=new int[]{2,2,2,2,2,2,2};
arr8[3]=new int[5];
for (int j=0;j< arr8.length;j++){
System.out.println("");
for (int i =0;i<arr8[j].length;i++){
System.out.print(arr8[j][i]+"");
}
}

字符串和容器

PS:在 Java 里,**<>** 叫泛型****(Generics),最核心的作用就是:给集合 / 类指定 “装什么类型的数据”<String> 意思就是:这个 list 只能装字符串,不能装数字、对象,装别的就报错。

字符串

1
2
3
4
String s1=new String("aaaaaaa");//在堆里
String s2="hijk";//在栈里
StringBuffer sb =new StringBuffer(s2);//省内存且在线程里更安全
StringBuilder sbb=new StringBuilder(s1);//省内存但是多线程不安全

容器

  • List:有序、可重复、有索引
  • Set:无序、不可重复、无索引
  • Queue:队列

Map 双列集合(存键值对 key=value)

List 系列(有序可重复)

1.
2. ArrayList

  1. 底层:数组
  2. 特点:查询快、增删慢、线程不安全、效率高
  3. 日常最常用
  4. LinkedList
    1. 底层:双向链表
    2. 特点:查询慢、首尾增删快
    3. 适合频繁头尾增删
  5. Vector
    1. 底层数组、线程安全、效率极低,基本不用

List 常用方法add()、remove()、set()、get()、size()、clear()

Set 系列(无序去重)

  1. HashSet
    1. 底层:哈希表
    2. 无序、去重、查询快
  2. LinkedHashSet
    1. 有序存取、去重
  3. TreeSet
    1. 自动升序排序

Map 键值对(key 唯一)

  1. HashMap
    1. 无序、查询最快、线程不安全
    2. 日常最常用
  2. LinkedHashMap
    1. 存取有序
  3. TreeMap
    1. key 自动排序
  4. Hashtable
    1. 线程安全、效率低、过时不用

Map 常用put () 存、get () 取、remove 删、keySet 遍历

大遍历方式

  1. 普通 for:只用 List
  2. 增强 for:所有集合通用
  3. 迭代器 Iterator:老写法

线程安全速记

  • 不安全(快):ArrayList、HashMap、HashSetStringBuilder
  • 安全(慢):Vector、Hashtable、StringBuffer

选型口诀

  1. 有序可重复 → ArrayList
  2. 去重 → HashSet
  3. 排序 → TreeSet/TreeMap
  4. 键值对 → HashMap
  5. 频繁首尾增删 → LinkedList
  6. 单线程全用不安全,多线程再换安全类

异常

出现了意想不到的错误,直接抛出

Throwable

分为异常(Exception)和错误(Error)两个都是Throwable的子类

异常又分为运行时的异常和非运行时的异常

但是每一个都加trycatch会很影响效率和资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
try {
// 可能抛出异常的业务代码(受监控区域)
} catch (ExceptionType1 e) {
// 处理ExceptionType1类型的异常
} catch (ExceptionType2 e) {
// 处理ExceptionType2类型的异常
} finally {
// 无论是否发生异常,都会执行的代码(资源释放等)后面的代码也不执行了

}
//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {
public static void main(String[] args) {
try{
int m = Integer.parseInt("334sdas");//Integer.parseInt的作用是将传入参数能转成int的就转成int
System.out.println(m);}
// catch (NumberFormatException numberFormatException){
// /**抛出异常的分类层级关系
// * java.lang.Object
// * ↳ java.lang.Throwable
// * ↳ java.lang.Exception
// * ↳ java.lang.RuntimeException
// * ↳ java.lang.IllegalArgumentException
// * ↳ java.lang.NumberFormatException
// **/
// numberFormatException.printStackTrace();
// System.out.println(numberFormatException.getMessage());
// }
catch (Exception e){
// e.printStackTrace();
System.out.println(e.getMessage());
}

}
}

自定义异常

内置异常类型不能满足程序设计的需求时,就可以设计自己的Java类库或者框架;

语法:

1
<class> <自定义异常名><extends><Exception>

一般自定义异常类包含两个构造方法:一个是无参的默认构造方法。另一个是构造方法以字符串的形式接收一个定制的异常消息,并且将该消息传递给父类的构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//main:
//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {

static int div(int a,int b) throws MyException{
if(b==0)
throw new MyException("分母不能为0");
return a/b;
}
public static void main(String[] args){
try{
System.out.println(div(8,0));//打开操作
}catch (MyException e){
System.out.println("catch被捕捉到");
System.out.println(e.getMessage());
}
finally {
System.out.println("catch没有被捕捉到");
//关闭操作,可能会出现内存溢出
}
}
}
//MyException:
public class MyException extends Exception{
String msg;
public MyException(String message) {
msg=message;
}

@Override
public String getMessage() {
return msg;
}
}

输入输出数据流:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {
//打印命令行参数
public static void main(String[] args) {
for (int i=0;i< args.length;i++){
System.out.println("参数"+i+":"+args[i]);
}
//标准的io System.in System.out
int userInput;
System.out.println("请输入:");
try{
while((userInput = System.in.read())!='q'){
System.out.println((char) userInput );
}

}catch (IOException e){
System.out.println(e.toString());
}
//输入标准的代码,注意在io操作的时候需要写异常IOException;
InputStreamReader ir =new InputStreamReader(System.in);
BufferedReader in =new BufferedReader(ir);
String s;
try{while(true){
//每次获取一行
s=in.readLine();
if (s.equals("exit")){
break; }
System.out.println(s);
}

}catch (IOException e){}
}
}

文件数据流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

//TIP 要<b>运行</b>代码,请按 <shortcut actionId="Run"/> 或
// 点击装订区域中的 <icon src="AllIcons.Actions.Execute"/> 图标。
public class Main {
public static void main(String[] args) {

try{
byte buff[]=new byte[1024];
int cnt =System.in.read(buff);//输入,将输入放到buff,返回读到的实际长度
FileOutputStream fileOutputStream=new FileOutputStream("read.txt",true);//创建输出实例,选择追加
fileOutputStream.write(buff,0,cnt);//将buff[]的内容写入,偏移量为0,一共写cnt个字符
fileOutputStream.close();//关闭输出流
}
catch(IOException ioe){
ioe.printStackTrace();
}
FileInputStream fileInputStream=null ;
try{
File file = new File("read.txt");
long len=file.length();//获取文件长度
int len1=(int)len;//强制转换为int型
fileInputStream =new FileInputStream("read.txt");//读取read.txt
byte buffer[] =new byte[len1];//定义一个buffer数组
//循环体
int readlen=-1;
while((readlen = fileInputStream.read(buffer,0, buffer.length))!=-1 && readlen>0){
System.out.println(new String(buffer).trim());
}
}
catch (IOException e){
System.out.println("没读到");
}
}

}