编辑
绪论
Java语言的前身-----Oak语言
Java语言的创始人----James Gosling
Java语言的特性
简单性 | 网络特性 | 面向对象 | 平台无关性/可移植性 |
鲁棒性 | 安全性 | 多线程性 | 解释性 |
Java工作原理:JVM机制------.java->.class(字节码形式)
程序员编好一个.java的原文件,随后通过编译成.class的虚拟机代码,是字节码程序,这些代码会进入到Java虚拟机中,不断的加载,检测安全性,如果不安全就会抛出异常,最后编译好成为本地计算机可以执行的代码,从而实现与平台无关。
在包里面 src\helloworld> javac -d . helloworld.java //java的类命令 src\helloworld> java helloworld.helloworld 不在包里面 src> javac hellworld.java src> java helloworld
Java中的内存
堆内存:存储new出来的对象和数组。先进先出
栈内存:存储方法,局部变量。先进后出
结构化程序设计
标志符与关键字
1 Java的字符集合:Unicode字符
2 特殊字符和编码
0 | 48 |
A | 65 |
a | 97 |
3 标志符规则
开头:A~Z a~z _ $ 汉字
后面:数字 A~Z a~z _ $ 汉字
错误标志符:关键字,false,true,null
关键字
abstract class extends implements null strictfp true assert const false import package super try boolean continue final instanceof private switch void break default finally int protected synchronized volatile byte do float interface public this while case double for long return throw catch else goto native short throws char enum if new static transient
4 习惯性的定义
包:小写
类和接口:开头大写 Teacher
方法和变量:首字符小写,第二个字符大写
常量:全大写 PI
数据类型
5 基本数据类型 编辑
6 引用数据类型:类,接口,数组
注意点 boolean不是0和1
boolean的全局变量初始值为false
char类型的全局变量的初始值为'/u0000'
引用数据类型全局变量的初始值为null
int i; System.out.println(i);
方法内部(局部变量):报错
方法外部(全局变量):自动赋值为0
7 final赋值问题
常量 final int a=10(final的作用为变量不可更改或类不可被继承)
final 在全局变量中必须当场赋值,在局部变量无所谓
区别于static,static必须要在全局中,但是有没有初值无所谓
8 字符的写法
任意字符 | '猫' |
Unicode | '\u0061' |
转义字符 | '\t' |
9 整数不同进制的写法
八进制 | 0开头 |
十六进制 | 0x或者0X开头 |
10 变量
String name:name存储的是该对象的首地址
转换:隐式类型转换(低转强),显示类型转换(强制类型转换,强转低)
编辑编辑
注意:去掉小数部分:强制浮点类型转换整型
四舍五入:int i=(int)(d+0.5)
布尔类型不可与其他类型进行转换
char类型和short、byte类型需要人工进行强制转换
运算符
11 注意点
- /结果为整数:3/6=0
- %结果符号只与第一个操作数的符号相同:15.25%(0.5)=0.25
- double y=0.1+0.1+0.1+~0.1(10个0.1)=0.99999
- 比较两个浮点数
- 1定义epsilon=1e-5(10的负5次方)
- 2(((d2-epsilon)<d1)&&(d1<(d2+epsilon)))
- &&和||有短路原则,可以由第一个布尔值来直接结束
- d1^d2:异或,不能同时为相同的值
- 位运算符
>> | 右移,正补0,负补1 |
>>> | 右移动,用0来填 |
<< | 左移,不分正负,低位补0 |
- 位运算:a^(a^b)=b 技巧:括号拆掉,aa消掉
- i*=2+3 == i=i*(2+3)
- a+++b == a+b
- >>对于byte、short、char编译错误
- 只有负数>>才会补1
- 条件?选择1:选择2
控制结构
12 if 和switch
if
else if
else
switch (表达式)
{
case 值1:
语句
break;
~
default:
语句
}
逻辑关系,先从case开始
有相同的case:从该case一直执行,直到遇到break,若没有break就直接结束
没有相同的case:从default一直执行,直到遇到break
例子
int main() { int i = 2; switch (i) { case 1: printf("%s\n", "case 1"); default: printf("%s\n", "default"); case 2: printf("%s\n", "case 2"); case 3: printf("%s\n", "case 3"); } return 0; }
若i=2输出
case 2
case 3
若i=0输出
default
case 2
case 3
continue | 跳过下一个语句,但是仍然在循环体内 |
break | 跳出该循环体 |
13 加强for循环
优点:不必写数组的上限,提高准确率,整洁
比如
for(int x;a数组) System.out.println(x);
14 补充知识:java如何输入
import java.util.Scanner//输入的包 Scanner stdion=new Scanner(System.in)//固定格式,但只要写一个就好了 int n= stdio.nextInt();//不同的类型对对应不同的stdio.next类型
结构化程序设计例题
例子:请输入一个数字n,输出从1到n的阶乘和
package test import java.util.Scanenr public class JieChengHe{ public static void main(String[] args) {Scanner stdio=new Scanner(System.in); int n=stdio.nextInt(); int sum=0;int k=1; for(int i=1;i<=n;i++) {for(int j=1;j<=i;j=++) k*=j; } sum+=k; k=1; } System.out.println("n的阶乘和为"+n); }
面向对象程序设计
面向对象技术三大特性:继承性,多态性,封装性
类,域,方法和实例对象
1 类的自然语言(面相对象)
一个物体有什么特点(属性)有什么行为(方法):与c语言不同,定义是java最需要考虑的
2 类的定义
[类修饰词] class 类名 [extends 父类名][implements 接口名称列表]
{类体 }
3 构造器(构造方法):与类的名字一样
构造器的本质:对象初始化,赋初值
任意一个类都会有一个默认的构造方法,只是啥内容也没有
每当你创造一个新的实例对象的时候,若new b()就执行无参的构造方法,若new b(Sting a)就执行有参的构造方法
4 成员方法:跟原来c语言一样,啥名字都可以
public class Test {int i=1,j=1; Test() {i=i+j; } Test(int i) {i++;} }
5 参数传递方式
1 形参为简单数据类型
形参为引用数据类型
2 改变引用,影响实参
3 不改变引用,不影响实参
题目 x=1,y=2; p.setdate(x,y); 1 void setdate(int a,int b) {a=10,b=20;} 2 void setdate(Point p) {p.x=10; p.y=20;} 3 void setdate(Point p) p=new Point(); p.x=10; p.y=20; }
引用数据类型传递的是参数的首地址
6 方法的重载:同一个类中有多个构造方法
形式:参数数量不一样+数据类型不一样
作用:有很好的可延展性
比如 add(int a,intb)和 add(float a,floatb)
简化代码可以用this,比如
重载和多态的区别:重载是一个类里面的,多态是不同类之间的,主要是针对子类继承父类重写方法
重载与重写(覆盖)的区别:重写也是针对于子类与父类的,重写包括多态
int c1,c2; public apple(int a,int b) { apple.a=1; apple.b=2; } public apple(int a ,int b,int c) { this.(a, b); apple.c=3; }
7 类成员方法,变量:所有实例共享(比如LOL中的英雄生命,物理攻击)
特征:前面有 static(静态成员)
public class ok{ int a=0 static b=0; void y() a++; b++;} public static void main(String[] args) {ok ok1=new ok(); ok ok2=new ok(); ok1.y; ok1.y; ok2.y; System.out.println(ok1.a+" "+ok1.b); System.out.println(ok2.a+" "+ok2.b); }
执行结果
2 3
1 3
8 类实例对象的生命周期
创建->使用->废弃->垃圾的回收
Book book1 = new Book(1); new Book(2); new Book(3);
Book(1)有实例对象指向,不会被回收
Book(2)和Book(3)没有实例对象指向,会被回收
申请回收代码: System.gc();
若加一行:book1=null; 那么book1也会被回收
继承性
1 格式
[类修饰词] class 类名 [extends 父类名] [implements 接口名称列表] {}
2 构造方法
//B类继承A类 public class B extends A { //B带参的构造方法 B(String name) { super(name); System.out.println("B-->" + name); } public static void main(String[] args) { B b = new B("good"); } } //创建A类 class A { //A带参的构造方法 A(String name) { System.out.println("A-->" + name); } }
输出结果
A-->good
B-->good
原因
子类继承时会默认在第一个构造方法下面第一行加了super()
super()代表继承父类无参数的构造方法
这题中发现父类没有无参数的构造方法,那就先跳过,然后super(name)执行父类有参数的构造方法,最后执行自己的构造方法
如果子类有super就不会默认加上super()
如果父类为A(string a),子类必须写上第一条super(“ok”)
也就是说,父类如果只有带参的构造方法,子类也必须要有一个带参的构造方法,该构造方法里面必须要加一行super(m)
3 调用父类成员域
super.XX
4 调用当前成员域或方法
this(主要解决局部变量和成员域名字一样,所以不常用)
5 子类与父类的转换
子类直接变父类
父类强制转换成子类
强制转换只有一种情况下不行
fulei a = new fulei(); zilei b= (zilei) a;
是错误的!因为a没有子类,那么子类b不可以得到空子类的a。如果正在两行代码中间加上一行新建一个子类,且a指向该子类,那么这个代码就正确了。
6 实例对象
Z a=new Z(); F b=new F(); F c=a;
判断变量是不是某个类的实例变量: 变量 instanceof 类
a instanceof F/Z ture
b instanceof Z false
c instanceof F/Z ture
原因:a为子类实例,它也算是父类实例,父类c指向a,a为子类,则c也子类
注意:子类变父类,但是父类变量指的是子类的变量!
注意:类与变量之间的转换问题是不一样的,变量转换了就是真转换了,但是类就算转换了还是有指向的问题的
编辑
7父类中的private
如果父类中使用private方法,子类虽然会继承,但是不能访问该方法
8超类
被继承的类成为超类
9Object类
继承最祖先的类:Object类,存放在Java.lang中
clone()方法:返回值就是这个拷贝实例
场景:已有一个实例对象
equals()方法:比较两个实例
toString()方法:以字符串的方法来返回该实例信息
多态性
静态多态:同个类中同名方法的重载(就是方法内的参数不同)
动态多态:三大条件
继承
重写(覆盖)
**父类引用指向子类对象**
public class father { int m=0; public void ok() { System.out.println("father"); } } public class child extends father { int m=1; public void ok() { System.out.println("child"); } public static void main(String a[]) { father f1=new father() f1=new chile(); f1.ok(); System.out.println(f1.m); } } //结果是child 0
就是父类中有一种方法,然后其继承的子类也有一些相同的方法,但是该方法内容是有不同的内容,随后在父类中调用该方法
当父类的对象对子类的实例引用时,这个父类对象所访问的成员必须是父类中已经有的
也就是说子类自己创建了的成员,而不是从父类中继承,那么父类不可访问该成员
当父类被强制转换成子类时,子类的所有成员(方法,域)才可以被访问
封装性
四大变量修饰符 | 自身 | 同包子类 | 不同包子类 | 同包类 | 其他类 |
private | √ | ||||
package(没有修饰符也表示这个) | √ | √ | √ | ||
protected | √ | √ | √ | √ | |
public(一般用于方法,可以被调用) | √ | √ | √ | √ | √ |
一个java源文件多只能包含一个public类,且该类必须与其所在的文件同名
protected与public的区别:在两个包中,两个类之间是没有继承关系的,public都是可以互相访问,但是protected不行,protected是必须要有继承关系的两个类才可以跨包。
修饰词abstract,static和final
1 abstract
作用:与接口很像的东西:在父类定义一个方法,具体内容啥也没有,然后在子类继承后必须要有这个函数,必须加上具体的内容
在父类中需要加上abstract而在子类中可以不用加上abstract
与接口的区别
子类只能继承一个抽象类
子类可以有多个接口
哪些有抽象类
能否有抽象类? | |
类,接口,成员方法 | √ |
成员域,构造方法 | × |
接口一定有抽象属性
2 static
static方法里调用其他方法必须要先创建一个对象
static变量就是一个超级全局变量,你创建的所有类都是共享的,一个类中变了所有的类都会变化
int a=0; static int b=0; public static void main(String[] args) { c100 A=new c100(); c100 B=new c100(); A.a++; B.a++; A.b++; B.b++; System.out.println(A.a); System.out.println(B.a); System.out.println(A.b); System.out.println(B.b);
结果
1
1
2
2
分析:a为全局变量,无论多少个创建的类修改了它,新的还是0。但是b为静态变量,每个类都会完全修改它
static int m=0 ; void ok() { static int m=0 ; }
第一个(√)
第二个(×)
static变量的创建只能在全局位置
static方法只能访问static变量,非static方法即可访问ststic变量也可访问非static变量
static方法无须创建对象即可直接使用
3 final
不可以被继承
可以修饰的对象有:(与abstract相对应)
不具抽象的(类,成员)以及接口的成员域 | √ |
抽象的(类,成员),接口,构造方法,接口的成员方法 | × |
只能赋值一次
如final PI=3.1415926
接口
1 创建一个接口
File->New->Interface
2 格式
[接口修饰词]interface 接口名 [extends 接口名称列表] {}
public | 必须与java的文件名一样,跟类是一样的道理 |
abstract | 默认 |
strictfp | 遵循IEEE 754算法国际标准 |
3接口的成员域和成员方法
接口的所有成员域都有 public,static和final属性
接口的所有成员方法都有public和abstract属性
接口的成员方法只能是抽象的,所以为public/abstract 返回类型 方法名 (参数);
内部类
1出现原因:很好的实现隐藏,一般来说非内部类不方便使用private和protected
种类 | 运用方法 | 特点 |
非静态内部类 | 要实例化内部类必须先实例化外部类 | 可以任意访问外部 |
静态内部类 | 可以直接实例化内部类 | 只能访问外部类的静态变量和方法 |
匿名类 | 声明一个类的同时实例化它 | 实例一个对象在其下面直接{设计新方法} 使用外部变量必须为final,不加也没关系,因为系统会自动给你加上final- |
本地类 | 有名字的匿名类 |
2匿名类
public class Hero() { Hero h =new Hero() { public void attack() {System.out.println("杀疯了");} } h.attack(); }
3本地类
public class Hero{ class SomeHero extends Hero(){ void attack() {System.out.println("杀疯了")}} SomeHero h = new SomeHero(); h.attack(); }
equals和==
== | 基本数据类型:比较值 引用数据类型:比较地址 |
equals重写过(或Sring是系统自动重写的) | 先比较地址,地址相同直接true,如果地址不相等,再比较值,如果值相等也输出true |
equals没有重写过 | 比较地址 |
java常用函数
看菜鸟教程
数学方法:
Math.round(m)四舍五入
Math.random()有0无1
Math.sqrt(m)开方
Math.pow(2,4)2的4次方
Math.PI π
Math.E e
数组,字符串,向量和哈希表
数组
1和类接口一样都是引用数据类型
2数组与字符串
char a[];//定义一个数组 char a[]={'a','b'};//初始化数组 char a[]=new char[3];//定义一个数组对象 a[3]='a';//字符数组对象初始化 String s[]=new String[3];//定义一个字符串对象 s[0]=new String("czj");//字符串数组初始化
每个数组在内存中存储的结构,除了本身内容之外,还有一个length,且可以调用的
3多维数组
三种初始化方法
1)直接创建多维数组对象
int [][]max=new int[2][2];
2)从高维开始逐维创建数组对象
int [][][]mat=new int [3][][];//三维 mat[0]=new int [2][];//二维 mat[0][0]=new int [2];//一维
3)从高维开始逐维创建数组对象
String [][]mat={{new String ("Hello"), new String("world")}, {new String("hello"),new String ("java")}};
字符串
1数字转字符串
方法一:int i=5;
String a=String.valueOf(i); 不管数据类型怎么变,valueOf都是不可以变的
方法二:Integer i=6;
String a=i.toString();
2字符串转数字
String a="999";
int i=Integer.parseInt(a); 不管数据类型怎么变,parse~都是不可以变的、
float j= Float.parseFloat(a);
3格式化的输出与format
C语言中的print和format的效果基本上是一样的,但是format还有附加的函数功能
如System.out.format("%s只有%dcm",a,b);
特殊功能:
将s换成S后:小写转换成大写
4字符串的拼装
方法一:直接s1+s2
方法二:格式化字符串
String sentenceFormat ="%s 在进行了连续 %d 次击杀后,获得了 %s 的称号%n"; String sentence2 = String.format(sentenceFormat, name,kill,title); System.out.println(sentence2);
5通过字符数组创建一个字符串对象
char []cs=new char []{'牛','马','人'}; String hero =new String(cs);
6字符串的各种操作
方法 | 作用 |
m.charAt(3) | 获得指定位置的字符 |
char [] cs = m.toCharArray(); | 将字符串转换为字符数组 |
String s2 = m.substring(3 ,5); |
截取子字符串,第3个到第5个 |
String a[] = m.split("," ); |
根据某个符号进行分隔 |
m.trim() | 去掉首尾空格 |
m.toLowerCase m.toUpperCase | 全部变成小写/大写 |
m.indexOf('超神' ,5 ) |
从位置5开始,第一次出现超神的位置 |
m.indexOf('A') | 字符A第一次出现的位置 |
m.contains("击杀" ) |
包含 |
m.replaceAll ("击杀" , "被击杀" ) |
替换所有的 |
m.replaceFirst | 替换第一个 |
7字符串的比较
方法 | 作用 |
equal和== | 看上一章的末尾处 |
s1.equalsIgnoreCase(s2) | 忽略大小写比较内容 |
s1.startsWith() | 是否以~开始 |
s1.endsWith | 是否以~结束 |
8StringBuffer
定义
String a="好的呢"; StringBuffer b=new StringBuffer(a);
String定义后是难以变化的
StringBuffer是可变长的字符串(增删插反)
若StringBuffer sb="0123456"
函数 | 功能 |
sb.append("be light" ); |
在最后追加 |
sb.delete(1, 2); | 从第1个开始删后面1个 023456 |
sb.insert(4 , "p" ); |
从第4个开始后插个p 0123p456 |
sb.reverse(); | 反转 |
sb.substring(2,4) | 从第2个开始往后找2个 23 |
sb.capacity() |
容量大小 23详见下方 |
sb.length() | 长度 7 |
sb.setLength(4) | 设置缓冲区的长度为4,由于比长度短,所以字符的长度也变为4 所以输出为0123 |
sb.charAt(4) |
返回第(4+1)个字符 4 |
sb.setChartAt(4,a) | 将第(4+1)个字符换为a 0123a56 |
sb.indexOf("234") | 找出第一个与“234”相同的子序列的开始位置 2 |
sb.replace(2,3,"hello") | 在原来从第2+1开始到4之间换为hello 01hello3456 |
9为什么StringBuffer可以变长呢?
比如new StringBuffer("ok");其内部长度并不是3,而是3+16(16是不同的JDK是不同的),如果实际长度超过了这个的话,就会又分配一个长度为19的内存给它
向量
1背景:可变长度的数组,与SrtingBuffer还可以自动增加容量
2导入接口java.util.Vector
3定义如
Vector <String> m = new Vector<String>(5,10); 初始容量为5,扩容为10
4其他的方法StringBuffer有的它基本都有,详细见书本
哈希表
1是最快得根据元素找位置方法
2java.util.Hashtable java.util.HashMap java.util.WeakHashMap
Hashtable | 支持同步(多线程访问,不会有错误访问数据),关键字和值都不允许为null |
HashMap | 关键字和值都允许为null |
WeakHashMap | 可以被系统回收,关键字和值都允许为null |
3装填因子
元素个数/总容量
一般建议是0.75,如果在定义的时候不强调,也是0.75
系统默认的0.75的作用是:实际容量会随着加入的元素而自动扩大,所以它会影响在啥时候扩大。实际的装填因子需要自己计算
4创建方法
方法1 String[]+new+put String[] s1={~}; Hashtable<String,Integer> h=new Hashtable<String,Integer>(800,0.77f); //800为初始容量,0.77f为装填因子,当然这个两个也都可以不要的 for(int i =0;i<s1.length;i++){h.put(s1[i],new Integer(i))}; //方法2
5方法
方法 | 作用 |
h.put("dudu",1); | 在下标为1装入duduo |
h.get("dudu") | |
h.clear() | 清空哈希表 |
h.contains("dudu") | |
h.isEmpty() | |
h.remove("dudu") | 删除dudu |
h.size() |
集合框架
基础
1背景:使用数组有很多的局限性,而集合框架可以自动增加,而且它存放的是多个对象
2使用泛型的容器----只能存放该种类型的
3使用Arrays进行排序
int a[] = {1, 2, 4, 5, 6, 7, 8, 8, 9, 9, 9, 6, 5, 54, 4, 3, 3,}; Arrays.sort(a);
注意Arrays.sort只能用作于数组(数字数组和字符串数组都是可以的),但是封装类是不可以的,所以就需要用到Collections集合,因为它更加的基础
//首先输入字符串,然后转化为字符数组,最后看条件是不是要转化为整数数组 Scanner sc = new Scanner(System.in); String line = sc.nextLine(); String[] p = line.split(" "); Vector<~> v = new Vector<>(); for (String x : p) {Vector.add(x);} 或者for (String x : p) {Vector.add(Integer.parseInt(x));} //如果是整数比大小 Collections.sort(v, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) return o2-o1); }}); //如果是字符串比大小 Collections.sort(v,new Comparator<String>(){ public int compare(String o1,String o2){ return o1.compareTo(o2); }}); //如果是字符串比长度 Collections.sort(v,new Comparator<String>(){ public int compare(String o1,String o2){ return o2.length()-o1.length(); }});
5使用Collections进行翻转
ArrayList m=new ArrayList(); m.add(31); m.add(6); m.add(56); Collections.reverse(m);
ArrayList类
编辑
StringTokenizer类
作用,可以方便对输入的数据以~符号进行划分
常用的方法
- 1. int countTokens():返回nextToken方法被调用的次数。
- 2. boolean hasMoreTokens():返回是否还有分隔符。
- 3. boolean hasMoreElements():判断枚举 (Enumeration) 对象中是否还有数据。
- 4. String nextToken():返回从当前位置到下一个分隔符的字符串。
- 5. Object nextElement():返回枚举 (Enumeration) 对象的下一个元素。
- 6. String nextToken(String delim):与 4 类似,以指定的分隔符返回结果。
//从键盘输入一字符串,采用StringTokenizer类将该字符串里的单词按照空格,逗号和句号分隔出来,统计单词数,并按单词出现的顺序打印出来 package q3; import java.util.*; public class q3 { public static void main(String argc[]) { Scanner s1=new Scanner(System.in); String s2=s1.nextLine(); StringTokenizer st1=new StringTokenizer(s2," ,."); int num=0; while(st1.hasMoreTokens()) { num++; System.out.println(st1.nextToken()); } System.out.println("单词总数是:"+num); } }
Number类
//xxxValue() //转换数据类型并返回 Integer x=5; System.out.println(x.byteValue()); //compareTo() //啥都可以比较,字符串有也可以比较 //equals()就不说了 //valueOf() //就是定义的时候给定参数 Integer b= Integer.valueOf("11",16);//先转为16进制然后将其赋值给b //toString() //直接返回值,我觉得没啥软用 //parseInt() //字符串转化为各种Number型 int x=Integer.parseInt("456");
文件与数据流
编辑
输入流与输出流
1流:两个程序,文件之间的数据交流的实现方式
抽象类:InputStream、OutputStream、Reader、Writer
2创建流
File f=new File("E//hello//h.txt");
创建输入流:FileInputStream fis =
new
FileInputStream(f);
创建输出流:FileOutputStream fis =
new
FileOutputStream(f);
3字节流
字母转化为数字来存放在计算机中
//Scanner,汉字可以输出 File f=new File("E:\\text\\hello.txt"); Scanner sc =new Scanner(f); while(sc.hasNextLine()) { System.out.println(sc.nextLine()); } //InputStream && read,只能输出字幕 File f=new File("E:\\text\\hello.txt"); FileInputStream fis=new FileInputStream(f); byte[] all=new byte[(int)f.length()]; fis.read(all); for(byte b:all) { System.out.println((char)b); } //OutoutStream && write,将内容写入文件中 FileOutputStream fos=new FileOutputStream(f); byte[] shuru[]={88,80}; fos.write(shuru);
4字符流
直接使用字符读写文件
//读文件 File f = new File("d:/lol.txt"); FileReader fr = new FileReader(f)) char[] all = new char[(int) f.length()]; fr.read(all); for (char b : all) {System.out.println(b);} //写文件 String date="hello java"; char cs[]=data.toCharArray(); //不管怎么样只要有一个char类型的数组就可以了 fr.write(cs);
5缓存流**重点
背景:不同于字节流字符流一个个的读取,它是一行行的读取
除此之外,字节和字符流都是可以支持的。
//实现将文件的复制 import java.io.*; public class copy { public static void main(String a[]) { try( BufferedWriter f2=new BufferedWriter(new FileWriter("E:\\text\\hello.txt")); BufferedReader f1=new BufferedReader(new FileReader("E:\\text\\hello1.txt")); ) { int judge=0; while((judge=f1.read())!=-1) { f2.write(judge); } } catch (IOException e) { e.printStackTrace(); } } }
//读取数据 File ff = new File("E:\\text\\hello.txt"); try( FileReader fr = new FileReader(ff); BufferedReader br = new BufferedReader(fr); ) { while (true) { // 一次读一行 String line = br.readLine(); if (null == line) break; System.out.println(line); } } //写数据 File ff = new File("E:\\text\\hello.txt"); try( FileWriter f2 = new FileWriter(ff); ) { String m="hello boy"; f2.write(m); }
import java.io.*; //实现从一个文件读取数据一直追加到另一个文件的末尾 public class copy { public static void main(String a[]) { try( FileWriter fw=new FileWriter("E:\\text\\hello.txt",true); BufferedWriter f2=new BufferedWriter(fw); FileReader fr=new FileReader("E:\\text\\hello1.txt"); BufferedReader f1=new BufferedReader(fr); ) { String s1; while((s1=f1.readLine())!=null) { f2.write(s1); } f2.flush(); } catch (IOException e) { e.printStackTrace(); } } }
6数据流
DataInputStream 数据输入流
DataOutputStream 数据输出流
File f =new File("d:/lol.txt"); try ( FileInputStream fis = new FileInputStream(f); DataInputStream dis =new DataInputStream(fis); ){ boolean b= dis.readBoolean(); int i = dis.readInt(); String str = dis.readUTF(); System.out.println("读取到布尔值:"+b); System.out.println("读取到整数:"+i); System.out.println("读取到字符串:"+str); } catch (IOException e) { e.printStackTrace(); }
7对象流
序列化:一个对象以流的形式进行传输
对象的类:必须要接入Serializable接口
什么不能序列化?
static属性+方法+与JVM相关的属性如Thread
import java.io.*; public class dd { public static void main(String[] args) { //创建一个Hero garen //要把Hero对象直接保存在文件上,务必让Hero类实现Serializable接口 Hero h = new Hero(); h.name = "garen"; h.hp = 616; //准备一个文件用于保存该对象 File f =new File("E:\\text\\hero.pp"); try( //创建对象输出流 FileOutputStream fos = new FileOutputStream(f); ObjectOutputStream oos =new ObjectOutputStream(fos); //创建对象输入流 FileInputStream fis = new FileInputStream(f); ObjectInputStream ois =new ObjectInputStream(fis); ) { oos.writeObject(h); Hero h2 = (Hero) ois.readObject(); System.out.println(h2.name); System.out.println(h2.hp); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
8 flush()
主要用在缓存流中,因为缓存流数据,输入到文件中比较慢,而flush的作用就是立马输出和刷新
9常见的编码
ISO-8859-1 ASCII 数字和西欧字母
GBK所有中文 GB2312简体中文 BIG5 繁体中文
UNICODE (统一码,万国码)
10 IO重定向
主要用在PrintStream当中(注意:它也是标准字节输入流)
System.setIn(~)
System.setOut(~)
PrintStream ps=new PrintStream(new FileOutputStream("E:\\text\\hero.pp")); System.setOut(ps); System.out.println("Hello World!");
这样你后面的使用System.out.println(~)实际将内容打印不是在控制台上,而是在真实的文件里面
11 Java的文件操作
File类:管理文件或者目录
序号 |
方法 |
返回类型 |
说明 |
1 |
getName() |
String |
获取文件名称 |
2 |
canRead() |
boolean |
判断File是否可读,可读返回true |
3 |
canWrite() |
boolean |
判断File是否可写,可写返回true |
4 |
exists() |
boolean |
判断File是否存在,存在返回true |
5 |
length() |
long |
获取File长度 |
6 |
getAbsolutePath() |
String |
获取File绝对路径 |
7 |
getParent() |
String |
获取File父目录 |
8 |
isFile(); |
boolean |
判断File是否是文件,是文件返回true |
9 |
isDirectory() |
boolean |
判断File是否是目录,是目录返回true |
10 |
isHidden() |
boolean |
判断File是否是隐藏文件,是返回true |
11 |
lastModified() |
long |
获取文件最后修改时间,时间是从1970 年午夜至最后修改时刻的毫秒数 |
12 |
mkdir() |
boolean |
创建目录,如果创建成功返回true,如果目录存在则不创建,并返回false |
1 |
list() |
String[] |
返回目录下的所有文件名 |
2 |
listFiles() |
File[] |
返回目录下的全部文件对象 |
3 |
list(FilenameFilter filter) |
String[] |
返回目录下的所有文件名(filter用于指定过滤文件的类型) |
4 |
listFiles( FilenameFilter filter) |
File() |
返回目录下的所有文件对象(filter用于指定过滤文件的类型) |
//创建一个文件 File f=new File("E:\\text\\hh.ttx"); try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); } //获取目录下的所有文件 File f=new File("E:\\text"); f.mkdir(); String list[]=f.list(); for(String kk:list) { System.out.println(kk); }
12 防止出现乱码
.writeUTF
.readUTF
异常
1异常的体系结构
编辑
Error:JVM内部错误,比如堆栈满了或者内存溢出
Runtime Exception(非受检异常):运行异常 比如空指针,下标越界,不需要手动处理,一旦错误,程序就终止运行,比如除法,一般是没有错误的,只有当除数为0的时候才会报错。
Check Exception(受检异常):除了Runtime的其他所有异常,需要手动处理异常(抛出或者处理到try catch)
2 throw与try catch
try catch定义:自己干活,try自己来监控异常,然后使用catch来处理异常
throws定义:让别人干活,出现在方法中,我不知道该怎么处理异常,那就直接向上抛出。
注意:当子类重写带有异常的方法的时候,子类抛出的范围不能大于父类抛出的范围
3throws与throw
throws声明异常,放在函数上(函数头部末尾)
throw抛出异常,放在函数里
如果是函数有抛出的异常是RuntimeException,且没有try,则不需要声明
如果不是Run~,则必须要声明
4异常的三种格式
//第一个格式: try { //执行程序代码,可能会出现异常 } catch() { //捕获异常并处理 } //第二个格式: try { //执行程序代码,可能会出现异常 } catch() { //捕获异常并处理 } finally { //一定会执行的代码; } //第三种格式 try { //执行程序代码,可能会出现异常 } finally { 一定会执行的代码; }
5 finally
finally语句是一定会被执行的,常用语回收资源,比如关闭数据库
只有一种情况下finally不会执行,那就是在之前执行了System.exit(0);
finally与final的区别:一个是执行的方法,一个是修饰符。
6 Throwable中的方法
- getMessage() 获取异常信息,返回字符串;
- toString() 获取异常类名和异常信息,返回字符串;
- printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void;
- printStackTrace(PrintStream s) 通常用该方法将异常内容保存在日志文件中,以便查阅。
7 自定义异常
步骤
1)继承已有异常类
2)写几个重载的构造方法
3)自定义的异常通过throw抛出
4)e.printStackTrace(),e.getMessage()方法获取异常信息
/自定义异常 Class DemoException extends Exception { DemoException(String message) { //因为父类中已经把异常信息的操作都完成了。 //所以子类只要在构造时,将异常信息通过super语句传递给父类即可 super(message); } }
//自定义异常 public class HelloWorld { public static void main(String[] args) { MyDemo m=new MyDemo(); try { int x=m.ok(3,-1); System.out.println("x="+x); } catch(FuShuException f) { System.out.println(f.toString()); System.out.println("错误的负数是:"+f.getValue()); } System.out.println("over"); } } class FuShuException extends Exception { private int value; FuShuException() { super(); } FuShuException(String msg,int value) { super(msg); this.value = value; } public int getValue() { return value; } } class MyDemo { int ok(int a,int b) throws FuShuException { if(b<0) throw new FuShuException("分母出现了是负数的情况--/ by fushu",b); return a/b; } }
编辑
8如果子类如覆盖了父类的方法
要么就不要抛出异常
要么就抛出更细的异常或者更它一样的异常
如果父类抛出多个异常,那么重写(覆盖)方法必须抛出那些异常的一个子类,不能抛出新的异常。
多线程
1创建一个线程
三种方法:继承,Runnable接口,匿名类