Java 基础学习(笔记),java基础学习笔记
Java 基础学习(笔记),java基础学习笔记
Java SE
--------------
this:
this只能在类的对象方法中使用。
this代表当前调用这个this所在的方法的对象的自身。
this可以在方法内区分同名的类的属性和参数名,有this的一定是属性,没有this的一定是方法的参数名
通过this[实参列表]可以调用本类中的构造器,必须注意,this必须是在方法中的第一行
------------------------------------
构造器:
1.方法名和类名一致
2.方法没有返回值没有void
3.参数可有可无
构造器语法:
public 类名(数据类型 参数名,...){}
目的:
创建对象
注意:如果类中没有带参数的构造器,就可以使用一个隐藏默认构造器来创建对象,如果一旦有带有参数的构造器,默认构造器就会被覆盖。我们可以显示的定义出来默认构造器就可以使用了。
----------------------------------
static:
修饰在属性上:
static 数据类型 变量名;
类属性访问:
类名.类属性名(推荐使用)
对象名.类属性名
类属性的生命周期:
User.class加载到jvm中时类属性就产生了。
JVM消失时候类属性就消失了
对象属性:
当对象被创建的时候就产生了
修饰在方法上:
类方法的调用
类名.类方法名(推荐,不需实例化对象)
对象.类方法名(需要实例化对象)
在类方法中不能使用对象的属性(this也不能使用)
类方法中只能使用类属性
----------------------------------
super:
1.子类实例化的过程父类的构造器先被调用,然后再调用子类的构造器
2.子类的被调用的时候父类的默认构造器就会被调用(父类如果存在着有参构造器,一定要把默认构造器显示的定义出来)
3.子类在调用父类的有参数的构造器的时候使用,super(参数列表...),这时父类的默认构造器就不会再被调用了.
---------------------------
final:
可以作用在类上 方法上 属性上
修饰在方法上:
则方法不能被重写
final写在权限修饰符的后面
修饰在属性上:
则属性的值不能再改变
修饰在类上:
则不能被继承
---------------------
抽象类:
当多个具体的实体类存在着共同的行为,但是有不同的表现,我们在父类继承过程中父类的方法具体实现不同确定,但是能确定的是他们都有这种行为。我们要把这种行为方法作为抽象方法
1.抽象类不能被实例化
2.抽象类必须被子类继承才能使用子类实例化
3.继承了抽象类的非抽象类必须实现抽象类的所有抽象方法
4.抽象类可以继承抽象类,这样不需要实现父类的方法
5.抽象类的抽象方法不能和private final static 共存
抽象类可以没有抽象方法
------------------------------------
接口:
1.接口中的方法的定义不需要Abstract来修饰,默认就是抽象的
2.接口是不可以实例化的,需要有类来实现接口的语法
3.接口中的方法不能和private static final共存
4.在接口中可以定义属性,可以通过接口的实现类的实例来访问,还可以通过接口名来访问(推荐),接口中的属性不能修改,我们接口中的属性默认都是final static的,通常在接口中来定义属性把它作为常量,常量的名字规范是单词大写。而且多个单词之间用下划线来分隔
5.接口可以继承接口(单继承)
-----------------------------------------------
接口和抽象类的区别
1.接口的所有方法都是抽象的,抽象类里面的方法可以使抽象的也可以不是抽象的
2.接口和抽象类都不能实例化,接口需要类来实现后实例化实现类,抽象类需要类来继承然后实例化子类。
3.抽象类只能单继承,接口可以多继承接口(jdk1.7),接口还可以多实现。
4.接口中的属性是static final类型的,抽象类中的属性跟普通类中的属性没有区别
5.接口中的方法默认就是抽象的不需要加abstract,抽象类中的抽象方法需要加abstract关键字
------------------------
继承多肽:
1.必须要有继承关系,在抽象中可以定义多肽的抽象方法,通过子类来继承这个抽象类然后复写抽象方法以达到动态的效果
2.多肽子类的实例可以赋给父类的引用(Teacher jt = new JavaTeacher();)
instanceof:可以判断我们多肽的引用变量到底是什么类型
接口多肽:接口的多肽基本上和类的继承的多肽一致,不同的是类的继承使用的是继承关系实现多肽,接口采用实现的方式实现多肽
------------------------------
Math类
自然对数:Math.E
圆周率: Math.PI
绝对值:Math.abs(-1.5)
把小数去掉整数加1 Math.ceil(12.1)
把小数位舍弃 Math.floor(12.9)
比较两个数的大小 Math.max(12.9 27)
比较两个数的大小 Math.min(12.9,27)
计算某个数的n次幂 Math.pow(3,3)
四舍五入 Math.round(4.5)
开平方 Math.sqrt(16)
--------------------------
Scanner:
//创建扫描器的对象
Scanner sc = new Scanner(System.in);
//获得从控制台输入的一个整数
int val = sc.nextInt();
//获得从控制台输入的一个字符串
int line = sc.nextLine();
------------------------------------------------
内部类:
类内部的类就是内部类
位置:把一个类定义到另一个类中,那么内部的类就是内部类
注意:内部类的对象不能直接创建
创建内部类的语法:外部类.内部类 变量名 = new 外部类对象.内部类对象
内部类的外部类的方法如果想要访问内部类的方法。必须创建内部类对象,根据内部类的对象来访问
私有内部类:
内部类被private来修饰:被private修饰的内部类只能在它所属的外部类中访问
外部类的权限只能是public或者是默认不写
静态内部类:
静态内部类的创建语法:外部类名.内部类名 变量名 = new 外部类名.内部类对象
匿名类:
new 接口{属性... 方法...};
局部内部类:.
匿名内部类:.
-----------------------------
权限修饰符:
同类中 同一个包(没有父子类关系) 不同包(有父子类关系) 不同包(没父子类关系)
private Y N N N
默认 Y Y N N
protected Y Y Y N
pulbic Y Y Y Y
----------------------------------------
java.lang.Object
toString --- 返回该字符串的字符串表示
hashCode --- 返回该对象的哈希码值
sout(s == s1); == 判断的两个对象的地址,两个对象的地址永远不相等
equals(); == 指定其他某个对象是否与此对象“相等”,当方法被重写时,通常有必要重写hashCode方法
finalize(); = 当垃圾回收期确定不存在对象的更多引用时,由对象垃圾回收器调用此方法(系统默认调用)
-------------------------------------------------------
eclipse的使用:
Window - Show view == 展示需要的视图
Console - 控制台
Window - Reset Perspective == 重置
Window - Show View - navigator == 使项目目录跟真实文件夹一样展示
Window - Show View - Outline == 大纲视图
Window - Show View - Hierarchy == 层次窗口
A:用于显示类之间的层次(继承)关系
B: 在当前类上,按F4就可以切换到该视窗,并查看层次关系,查看源码,当前类上F3,或者Ctrl+鼠 标点击
Package Explorer == 该视图显示当前工作空间的所有项目及项目中的文件
java Project -- 工程名字建议小写
Package -- 包名建议小写
工作空间的基本配置:
设置编译环境级别:Window - Preferences - Java - Compiler - JDK Compliance
运行环境:Window - Preferences - Java - installed JREs 高版本运行环境兼容低版本的编译环境
调整字体:
Window - perference - General - Appearance - Color and Fonts - 右边Basic - Text Font - Edit
注释设置:
Window - Preferences - Java - Code Style - Code Templates - Comments(Types类注释Method方法注释)
修改快捷键:
Window - Preferences - General - Keys
快捷键:
alt + / 内容辅助键 补充类或者接口名,帮我们起变量名,new 后面直接提示等
crtl + shift + f 对代码进行格式化
ctrl + shift + / 对选中的区域进行多行注释的封装
ctrl + shift + \ 用于取消多行注释,只要光标在多行注释中即可
alt + ↑ or ↓ 向上或者向下移动当前行或者选中行
ctrl + shift + x 将选中部分的字母大写
ctrl + shift + y 将选中部分的字母小写
ctrl + 1 光标放在编译中出现红色波浪线提示的内容上,在该快捷键可以获取建议的处理方式
F3 可以查看类或者方法的源码,前提是,改源码已经关联
try{}catch(){} 快捷键 Shift + Alt + z
代码生成:
右键 - Source - 代码生成策略
Generate Constructor using Fields 生成构造器
Generate Constructors from Sunerclass... 生成父类构造器
Override/Implement Methods 覆写父类的方法
------------------------------------
Debug:
1.让我们调试程序更加方便
2.想要测试,需要在程序中加入断点
3.运行debug as,打开debug视图
4.快捷键 F5跳入(方法里面) F6跳过 F7跳出(方法里面) drop to frame 调到方法的第一行
5.清除断点 在 Breakpoints 视窗中清除指定断点或者所有断点
------------------------------
异常:java中的异常机制为了提高我们程序的健壮性和容错性而存在
throwable(异常超类)
catch(异常类型 变量名)
String mes = e.getMessage(); //打印异常信息
e.printStackTrace(); //把异常打印出来
String ts = e.toString(); //打印出来具体的异常类和异常信息
try{}catch(){} 快捷键 Shift + Alt + z
运行时异常:RuntimesException
自定义异常:
我们自己定义的异常都是运行期的异常
自定义异常的步骤:
1.创建一个异常类继承RuntimeException;
2.继承RuntimeException的构造器
自定义异常 - 主动抛出异常
public static void buyItem(){
int stock = 0;
if(stock == 0){
//我们主动抛出异常
throw new StockException("库存不足");
}
}
---------------------------------
字符串判断:
boolean b = str.endWith(ld) //判断字符串是否以ld结尾
equalsIgnoreCase(); //不区分大小写的比较
contains(); //判断是否包含某段连续的字符串
startWith(); //判断是否以某段字符串开头
isEmpty(); //判断字符串是否是空串
length(); //判断字符串的长度
charAt(); //返回指定索引处的字符
indexOf(); //查找指定字符(或字符串)第一次出现的索引,如果返回-1说明不存在要查找的字符串
indexOf("", 索引); //从指定索引处查找第一次出现的字符串的索引,包含开始索引本身
lastIndexOf() //从后面开始查找第一次出现的索引
lastIndexOf("", 索引) //倒序查找
substring(); //获得子字符串,包括索引本身后面的所有字符
substring(索引,索引); //根据开始和结束的索引来获得子字符串,包括开始索引,不包括结束索引
getBytes(); //获得字符串对应的字节数组
toCharArray(); //把字符串转换成字符数组
String.valueOf(true); //把布尔类型转换为字符串类型等等...
toUpperCase(); //把字符串转换为大写
toLowerCase(); //把字符串转换为小写
concat(); //拼接字符串
split(); //分割字符串 返回的是一个String类型的数组
replace('', ''); //字符串中单个字符替换
replace("", ""); //字符串中字符串的替换
trim(); //去掉字符串两端的空格
-----------------------------------------------
StringBuffer(可变字符串) - 线程安全的
字符串加上任何类型返回的都是字符串
append(); //把可变字符串追加
capacity(); //可变字符串的容量
insert(); //在指定的位置插入字符串 注意不要出现字符串的索引越界
delete(); //删除索引所对应的值
deleteCharAt //删除其中某个索引的字符
repleace(start, end, str); //替换
reverse(); //字符串的反转
lastIndexOf(); //获得倒数第一次出现的字符串
----------------------------------------
随机数:
nextInt(); nextInt(100); //获得随机整数 //获得指定区间的随机数
nextFloat(); //...
--------------------------------
System:
System.arraycopy(arr2, 1, arr1, 3, 2);
第一个参数:要拷贝的数组
第二个参数:要拷贝的数组的起始索引
第三个参数:目标数组
第四个参数:目标数组的索引起始位置
第五个参数:要拷贝的长度
System.currentTimeMillis(); //获得当前事件的毫秒数,从1970年到现在的毫秒数
System.exit(0); //退出jvm
System.gc(); //调用垃圾回收器
System.getProperty(); //获取系统的信息等..
-------------------------------
包装类:
int - Integer
char - Character
Integer.MAX_VALUE //输出int的最大值
Integer.MIN_VALUE //输出int的最小值
inValue(); //将Integer - int转换
valueOf(); //将String、 int类型转换为Integer Integer转换为String
parseInt(); //将String类型转换为int类型
toString(); //将Integer - String
Integer + 空串 === 字符串类型
基本数据类型 --- 包装类 ==== 装箱(jdk1.5以后的特性,自动完成)
包装类 --- 基本数据类型 ==== 拆箱(自动完成)
int的默认值为0,integer默认值为null;
-------------------------------------
Date:
创建日期格式化的对象
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//把日期转换为字符串
String str = sdf.format(date);
syso(str);
parse(); //将字符串转换为日期 -- 有异常需要处理
getTime(); //....
Calendar(日历类):
Calendar ca = Calendar.getinstance(); -- 获得到他的子类,获得到日历
get(Calendar.xxx(年,月......)); -- 获取方法
set(Calendar.xxx(年,月......),设置); -- 设置方法
getTimeInMillis(); --- 获得日历相关的毫秒数
---------------------------------------
集合:
collection的常用方法:
add(); //添加
addAll(); coll.addAll(coll1) //把一个集合中的内容加入到另一个集合中
clear(); //移除集合中的所有元素
remove(); //移除指定元素的单个实例,如果存在的话。
removeAll(); //从集合中删除一个小集合的内容
contains(); //是否包含某个元素
containsAll(); //大集合中是否包含另一个小集合
isEmpty(); //判断集合中是否有元素
toArray(); //把集合转换成数组
迭代器(Iterator) --- Iterator iter = coll.iterator();(不能边迭代边添加)
hasNext() -- 如果仍有元素可以迭代,则返回ture
next() -- 返回迭代的下一个元素
//Shift + Alt + R -- 一起修改同名的变量
List(有序可重复) List的迭代器 ---ListIterator li = list.listIterator();(能边迭代边添加)
add(); //尾部添加
add(索引,"元素"); //有序添加
addAll(); //多个添加
addAll(索引,"元素"); //有序添加
size(); //获得集合的长度
get(); //根据索引来获得指定元素
hasPrevious(); //判断是否有前一个元素
previous(); //前一个元素
remove(1); //根据索引删除
remove("宋江"); //根据内容删除
removeAll(); //从列表中移除指定集合中包含的其所有元素
clear(); //移除元素中的所有元素
ArrayList(不是线程安全的) --- 对集合
LinkedList(不是线程安全的) --- 对集合中的栈的调节
addFirst(); -- 添加至头部
addLast(); -- 添加至尾部
element(); -- 获得头元素
getFirst(); -- 获得第一个元素
getLast(); -- 获得最后一个元素
poll(); -- 元素出栈
push(); -- 元素压栈
Vector(线程安全的) -- 线程安全的集合
Vector的迭代
Enumeration enums = v.elements();
while(enums.hasMoreElements()){
Object obj = enums.nextElements();
syso(obj);
}
泛型:
泛型的概念:集合中可以存储任何数据类型,实际情况都是在集合中存一种数据类型,我们可以通过泛型来指定这种数据类型。
例:Collection<String> sc = new ArrayList<String>(); --- 指定集合的类型为String类型
自定义泛型 ---- public class Demo<T>{ ... }
增强for循环
for(数据类型 变量:集合){ ... } --- 不是线程安全的
缺点:增强for循环有并发问题存在
Set:
HashSet: (不是线程安全的)
特点:无序性,元素不可重复, 最多只允许有一个NULL;
当Set集合中添加"对象"元素时,如果要判断两个对象是否相等,必须要重写equals和hashCode方法,
这两个方法都符合相等的条件才认为是相等的两个对象
(e.hash == hash && (k = e.key) == key || key.equals(k));
LinkedHashSet: (按照添加顺序排列)
特点:1.有序性
2.不能重复
3.允许有null,但是只能有一个
4.不是同步的(不是线程安全的)
TreeSet:
排序:自创类必须要实现一个接口Comparable<T>
compareTo(); //比较两个字符串,从第一个字符串开始比较相同索引的字符,如果出现第一个字符串的第一个字符比第二个字符串的第一个字符大,就可以判断整个字符串比第二个字符串大,如果两个字符串第一个字符相等,再去比较它们的第二个字符,同样遵守上述规律。
特点:1.自然排序
2.元素唯一性
3.不允许null存在
4.不是线程安全的
可变参数:
修饰符 返回值类型 方法名 (数据类型...变量){
public static int sum(int ... p){
return 0;
}
}
注意:int ... p 参数是一个int类型的数组,相当于int[] p
Arrays工具类:
特点:
数组的工具类,这里的方法都是静态的
1.把数组转换成字符串
2.对任意数组排序
3.对任意的数组做二分法查找
4.把数组转换成List
Arrays.toString(); //将数组类型转换为字符串
sort(); //排序(例如对数组元素的排序)
sort(参数,起始索引,结束索引); //局部排序(例如对素组内元素的局部排序)
二分法查找:
//二分法的查找是有序的数组
Arrays.binarySearch(数组,要查找的数值); --- 获得索引
把数组转成List:
Arrays.asList(); -- 把数组转换成List 注意:从数组转换过来IDElist不能添加和删除
Collections工具类:
Collection 是集合的接口
Collections 是操作集合的工具类
Collections.reverse(list); //集合的反转
Collections.shuffle(list); //随机打乱集合
Collections.sort(list); //排序
Collections.synchronizedList(list); //把list变成同步的(线程安全的)
外部比较器:创建一个比较器类来继承 Comparator;
步骤:1.封装一个Emp类,并且提供构造器和toString方法 和get/set方法
2.创建一个EmpComparator类用来继承Comparator 继承Compare方法实现排序过程
3.在list中添加元素 List<Emp> empList = new ArrayList<Emp>();
empList.add(new Emp(1,14));
4.利用Collection.sort(empList, new EmpComparator());并输出
Map:
HashMap TreeMap HashTable LinkedHashMap
Map特点:
1.数据成对出现
2.数据的键是唯一的
3.一个键只能对应一个值
4.值可以重复
5.键允许有一个为空,值可以有多个为空
put(); //存入键值对
putAll(); //从指定映射中将所有映射关系复制到此映射中
clear(); //清空Map;
remove(); //如果存在一个键的映射关系,则将其从此映射中移除
get(); //通过键获取值 返回值的类型
keySet(); //拿到Map中所有的键
containsKey(); //是否包含指定的Key
containsValue(); //是否包含指定的value
isEmpty(); //判断集合是否为空
Map遍历:
第一种:
//拿到Map中所有的键
Set<String> keys = map.keySet();
for(String key : keys){
Person p = map.get(key);
syso(p);
}
第二种:
//获得键值对set集合
Set<Entry<String, Person>> entry = map.entrySet();
for(Entry<String, Person> sp : entry){
//获得每一个项中的key和value
String key = sp.getKey();
Person value = sp.getValue();
syso(key + value);
}
HashMap:
特点:
1.HashMap是Map的实现类
2.允许多个null值和一个null键
3.HashMap中的元素没有顺序(跟添加的顺序无关)
4.HashMap不是线程安全的
Collection.SdynchronizedMap(map); //使线程安全
TreeMap:
特点:1.该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的Comparator进行排序,具体取决于 使用的构造方法。
2.可以按着Key来做排序
3.Key不能null,key不能重复,值可以有多个null
4.不是线程安全的
HashTable:(线程安全)
特点:
1.HashTable是map的实现类
2.不允许任何null值和null键
3.HashTable中的元素没有顺序(跟添加的顺序无关)
4.Hashtable是线程安全的
HashMap 和 HashTable的区别
1.都是键值对集合
2.HashMap允许有一个空键和多个空值 HashTable不允许有空值和空键
3.HashMap不是线程安全的,HashTable是线程安全的
LinkedHashMap:
特点:
1.LinkedHashMap是map的实现类
2.允许多个null值和一个null键
3.LinkedHashMap有顺序(添加的顺序)
4.LinkedHashMap不是线程安全的
------------------------------
文件构造器:
三种文件构造器 File("路径 / 文件名");
File("路径", "文件名");
File("File1" "文件名");
CreatNewFile(); -- 根据对象来创建文件返回boolean
mkdir(); -- 单级目录创建
mkdirs(); -- 多层目录创建
delete(); -- 删除文件或者目录。如果目录中不是空就删不掉,一定是空目录才可以删除
文件的相对路径:
使用相对路径来创建文件,不指定盘符,相对路径就是工程文件夹
在package里面来创建文件:
File file = new File("src/cn/tx/file/hello.txt"); --- 相对路径
文件的判断功能:
exists(); //判断文件是否存在
isFile(); //判断是否是文件
isDirectory(); //判断是否是文件夹
isAbsolute(); //判断文件是否是绝对路径
canRead(); //判断文件是否可读
canWrite(); //判断文件是否可写
isHidden(); //判断文件是否隐藏
文件的获取功能:
getAbsolutePath(); //获得文件的绝对路径
getPath(); //获得文件的相对路径
getName(); //获得文件名(包含后缀)
length(); //获取文件的容量大小
lastModified(); //创建时间对象
获取子文件:
//获取系统的根目录 -- File.listRoots();
File[] files = File.listRoots();
for(File file : files){
syso(file);
}
//获取指定木下的所有孩子文件 file.listFiles();
File file = new File("路径");
File[] files1 = file.listFiles();
for(File file2 : files1){
syso(file2);
}
//获得指定目录下的所有孩子文件的名字
String [] fileNames = file.list();
for(String fileName : fileNames){
syso(fileName);
}
递归:
递归就是方法调用方法自身,递归一定有跳出条件
//阶乘的遍历
例:int result = fn(5);
public static int fn(int n){
if(n >= 2){
return n * fn(n-1);
}
return 1;
}
//遍历文件夹内部的文件
File[] files = file.listFiles();
for(File file1 : files){
//如果是文件就删除
if(file1.isFile()){
file1.delete();
}else{
//如果是文件夹就继续遍历
deleteFile(file1)
}
}
------------------------------
IO:
输入流:从文件中读取数据,或者从键盘输入数据属于输入流
输出流:向文件中写入数据
字符输入流的超类: Reader; -- 子类 FileReader BufferedReader
字符输出流的超类: Writer; -- 子类 FileWriter BufferedWriter
字节输入流的超类:InputStream; -- FileInputStream
字节输出流的超类:OutputStream; -- FileOutputStream
字符流:
FileWriter:
构造器:
1.FileWriter(File file) --- 根据给定的File对象构造一个FileWriter对象
2.FileWriter(String fileName) --- 根据给定的文件名构造一个FileWriter对象
write(); //把内容写入文件
flush(); //清空缓存区,把内容写到文件(字符流的特点)
close(); //close关闭输出流时会先清理缓存区
两种构造器的使用(事先无需先创建文件):
+++++++++++++++++++++++++++++++++++++++++++
//第一种构造器的使用
public static void Demo01(){
File file = new File("C:\\Users\\张宜成\\Desktop\\a.txt");
FileWriter fw = null;
try {
fw = new FileWriter(file);
fw.write("HelloWorld");
fw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
//第二种构造器的使用
public static void Demo02(){
FileWriter fw = null;
try {
fw = new FileWriter("C:\\Users\\张宜成\\Desktop\\a.txt");
fw.write("张宜成");
fw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
+++++++++++++++++++++++++++++++++++++
FileWriter的追加构造器:
1.FileWriter(File file, boolean append)
-- 根据给定的File对象构造一个 FileWriter对象
2.FileWriter(String fileName, boolean append)
-- 根据给定的文件名以及指示是否附加写入数据的boolean值来构造FileWriter对象
构造器:(创建输出流的追加对象)
1.FileWriter fw = new FileWriter("b.txt", true);
2.FileWriter fw = new FileWriter(new File("b.txt"),true);
输出换行:
把文本写入文件中\n代表换行
问题是不同的环境下换行的方式也不一样
Windows:\r\n (内容换行为了兼容记事本使用这个)
Linux:\n
Mac:\r
FileWriter的写入功能:
FileWriter fw = new FileWriter(text.txt);
char[] chs = {'a','b','c','d'};
fw.write(chs); ---- a b c d
//把一部分的字符数组来写入到文件中,第一个参数是字符数组,第二个是开始索引,第三个是从开始索引开始取得字符串的长度
fw.write(chs, 1, 3); ----b c d
//通过int值来写入相应的字符
fw.write(100); --- d
//写入字符串
fw.write("100"); --- 100
//把一部分的字符串来写入到文件中,第一个参数是字符数组,第二个是开始索引,第三个是从开始索引开始取得字符串的长度
fw.write("helloworld", 2 ,2) --- ll
FileReader(输入流):
构造器:
1. FileReader(File file);
--- 在给定从读取数据的文件名的情况下创建一个FileReader
2. FileReader(String fileName)
--- 在给定从中读取数据的文件名的情况下创建一个新FileReader
read(); //读取单个字符,返回的是字符的ascil码
注:如果文件读取完毕,最后没有字符会返回- 1;
迭代(遍历):
int num = 0;
//通过循环读取字符,判断的跳出循环的标志是 num = -1;
while((num = fr.read()) != -1){
syso( (char)num ); //打印字符
}
字符输入流的读取方式
read(char[] cbuf) -- 将字符读入数组
read(char[] cbuf, int off, int len ) -- 将字符读入数组的某一部分
迭代(遍历):
//如果num的值是-1说明文件中的数据已经读完
char[] chs1 = new char[1024];
int len = -1;
//循环条件的判断的边界时fr.read(char[])如果返回-1说明文件已经读取完毕
while((len = fr.read(chs1)) != -1){
syso(new String(chs1, 0, len));
}文本文件的复制:C:\Users\张宜成\Desktop
拷贝文件方式1:
******************************
package cc.chengcheng;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class CopyDemo {
public static void main(String[] args) {
copy();
System.out.println("复制成功");
}
public static void copy(){
FileReader reader = null;
FileWriter writer = null;
try {
//创建文件读取对象
reader = new FileReader("C:\\Users\\张宜成\\Desktop\\Java SE.txt");
//创建文件写入对象
writer = new FileWriter("C:\\Users\\张宜成\\Desktop\\Java.txt");
int len = -1;
while((len = reader.read()) != -1){
writer.write(len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
if(writer != null){
//释放资源
try {
writer.close();
if(reader != null){
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
**************************
拷贝文件方式2:
核心代码:
//定义每次的读取的长度的对象
int len = -1;
//定义存储读取内容字符的数组
char[] chs = new char[1024];
//当len不等于-1就一直读取
while(len = reader.rad(chs) != -1){
//把读取的文件写入到目标文件中
writer.write(chs, 0, len);
}
高效缓冲区:
BufferedReader -- 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取
BufferedWriter -- 将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入
BufferedWriter(Writer out)
-- 创建一个使用默认大小输出缓冲区的缓冲字符输出流
BufferedReader(Reader in)
-- 创建一个使用默认大小输入缓冲区的缓冲字符输入流
BufferedWriter核心代码:
FileWriter fw = new FileWriter("d.txt");
BufferedWriter bw = new BufferedWriter(fw);
BufferedReader核心代码:
第一种:
int num = -1;
while((num = br.read()) != -1){
syso((char)num);
}
第二种:(最建议使用 数组方式 + 高效缓冲区)
char[] chs = new char[1024];
int len = -1;
while(len = br.read(chs) != -1){
syso(new String(chs, 0, len));
}
高效缓冲区的方法:
newLine(); //换行,相当于\r\n
readLine(); //使用高效输入流可以读取一行数据
代码:
String line = null;
//使用高效输入流可以读取一行数据
while((line = br.readLine()) != null){
syso(line);
}
使用高效缓冲区的流复制文件:
FileReader reader = null;
BufferedReader br = null;
FileWriter fw = null;
BufferedWriter bw = null;
//创建文件读取对象
reader = new FileReader("要读取文件的路径");
//创建高效缓冲区的输入流
br = new BufferedReader(reader);
//创建文件的对象
writer = new FileWriter("读取到的文件需要写入的路径");
//创建高效缓冲区的输出流
bw = new BufferedWriter(writer);
String line = null;
//读取数据并写入另一个文件中
while((line = br.readLine()) != null){
bw.write(line);
bw.newLine();
}
bw.flush();
字节流:
字节输入流:InputStream: 常用子类 FileInputStream
字节输出流:OutputStream: 常用字类 FileOutPutStream
FileOutputStream:
getBytes(); //把字符串变成字节数组
FileInputStrean:
构造器:
FileInputStram(File file)
--- 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File的对象file来指定
FileInputStream(String name)
--- 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定
读取方法:
read() 从此输入流中读取一个数据字节
read(byte[] b) 从此输入流中将最多b.length 个字节的数据读入一个byte数组中
read(byte[] b, int off, int len) 从此输入流中将最多len个字节的数据读入一个byte数组中
字节流的高效缓冲区
BufferedInputStream
BufferedOutputStream
装饰者模式
目的:给类的功能增强
继承也能给类的功能增强
字符流和字节流的转换桥梁
InputStreamReader类输入流转换应用 -- 是字节流通向字符流的桥梁
代码:
InputStream is = System.in;
//要想使用字符流的高效缓冲区来操作字节流需要转换
BufferedReader br = new BufferedReader(new InputStreamReader(is));
//定义输入的文件流
BufferedWriter bw = new BufferedWriter(new FileWriter("d.txt"));
OutputStreamWriter类输出流转换应用 -- 是字符流通向字节流的桥梁
代码:
BufferedReader br = new BufferedReader(new FileReader("c.txt"));
//创建字符流向字节流转换的对象
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
打印流:
打印流 -- 只做输出没有输入
PrintWriter : 字符打印流
特点:1.可以打印各种数据类型
2.封装了字符输出流,还可以,字符流和字节流的转换
3.可以使用自动刷新,则只有在调用println printf 或format时才可能完成此操作
4.可以直接向文件中写数据
*****************************
PrintWriter核心代码:
PrintWriter pw = null;
try {
pw = new PrintWriter("C:\\Users\\张宜成\\Desktop\\a.txt");
pw.print(true);
pw.print("哈哈哈");
pw.flush();
System.out.println("录入成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(pw != null){
pw.close();
}
}
************************************
PrintWriter pw = new PrintWriter(System.out); -- 将数据打印到控制台
PrintWriter pw = new PrintWriter(System.out, true); -- 设置自动刷新 Flush
属性集合Properties概述 -- 线程安全的 -- 不支持泛型
Properties类表示了一个持久的属性集。Properties可保存在流中或从流中加载。属性列表中每一个键及其对 应值都是一个字符串
特点:
1.继承于HashTable,是线程安全的键值对存储结构
2.Properties 可保存在流中或从流中加载
3.只能保存字符串的键值对
构造器:
Properties() 创建一个无默认值的空属性列表
常用方法:
getProperty(String key); 用指定的键在此属性列表中搜索属性
setProperty(String key, String value); 调用hashtablr的方法put
List(PrintWriter out) 将属性列表输出到指定的输出流
load(InputStream inStream) -- 从输入流中读取属性列表(键和元素对)
load(Reader reader) -- 按简单的面向行的格式从输入
核心代码:
//属性类不支持泛型
Properyies prop = new Properties();
FileReader fr = new FileReader("prop.txt");
//把字符数据读到prop对象中
prop.load(fr);
//获得数据
...
store(OutputStream out, String comments)
以适应使用load(InputStream) 方法加载到Properties表中的格式,将此Properties表中的属性列表(键和元素对)写入输出流
store (Writer writer, String comments)
以适合使用load(Reader)方法的格式,将此Properties表中的属性列表(键和元素对)写入输出字符
序列化流(对象流):
把对象以流的形式存储在硬盘上或者数据库中的过程就是写序列化流
序列化流:
对象输出流:ObjectOutputStream将java对象的基本数据类型和图形写入OutputStream
对象输出流:
ObjectInputStream对以前使用ObjectOutputStream写入的节本数据和对象进行反序列化
ObjectOutputStream的构造器
创建写入指定OutputStream的ObjectOutputStream
writeObject(p); -- 调用序列化对象的写入方法
如给向序列化某个对象,那么这个对象所对应的类必须实现类通过实现java.io.Serializable节后以启用其序列化功能,在序列化的过程中要手动指定要序列化的类的seriaVersionUID,这样可以在类改变后依然可以反序列化,否则会报错。
ObjectinputStream的构造器
ObjectInputStream(InputStream in)
创建从指定InputStream读取的ObjectInputStream
readObject(p); -- 调用序列化对象的读取方法
//给类一个指定的序列化版本的ID,如果这个类发生了变化不会影响反序列化
private static final long serialVersionUID = -值L;
-------------------------------------------
字符编码:
ASCII表:
用7bit来表示存储数据
ISO-8859-1:拉丁码表
用8bit来表示
GB2312:
简体中文编码(国际码)
GBK:
gb2312做了增强
GB18030:
对GBK做了增强
BIG5:
支持繁体
Unicode:
支持多种国家的语言,这是国际标准。有2个字节来存储
不管是什么字符都用2个字节,会有浪费
UTF-8:
支持多种国家的语言,针对不同的字符的范围给出不同的字节表示
核心代码:
String str = "中国";
byte[] bsGbk = str.getBytes(); //使用默认的编码来编码(gbk)
byte[] bsUtf8 = str.getBytes("UTF-8"); //使用UTF-8来编码
printByte(bsGbk); //调用方法打印编码值
syso(new String(bsGbk)); //打印编码值对应的字符(默认编码)
printByte(bsUtf8); //打印用UTF-8编码后的编码值
syso(new String(bsUtf8, "UTF-8"));
-------------------------------------------------
线程:
创建新执行线程有两种方法。一种方法是将类声明为Thread的子类。该子类应重写Thread类的run方法,接下来可以分配并启动该子类的实例
setName(); -- 设置该线程的名字
getName(); -- 获得该线程的名字
start(); -- 启动线程
注:线程启动的时候使用线程的start方法而不是run方法
创建线程的另一种方法是声明实现Runnable接口的类。该类然后实现run方法。然后可以分配该类的实例,在创建Thread时作为一个参数来传递并启动。
Thread.currentThread(); //返回当前正在运行的线程
Thread.currentThread().getName(); //返回当前正在运行的线程的名字
针对线程的安全性问题,我们需要使用同步(就是要加锁,共享资源只能一个人同时访问)锁
语法:
synchronize(锁对象){
//操作共享资源的代码
}
synchronized同步代码块的锁对象可以是任意类对象(线程的实现方式是使用继承于Thread),这个对象必须是线程了共享(静态的)。
同步代码块加在什么地方?
1.代码块被多个线程访问
2.代码块中有共享的数据
3.共享数据被多条语句操作
Synchronize同步代码块的锁对象可以是任意类对象(线程的实现方式是使用继承于Thread),这个对象必须是线程类共享(静态的)
Synchronize是可以加在方法上,如果是静态方法Synchronize的锁对象就是类的类对象,如果不是静态的方法 ,synchronize如果加在对象方法上,那么他的锁是this
线程的休眠
sleep(1000); //线程的休眠
线程的休眠是很必要的,在做服务端的时候为了减少服务器的压力我们需要休眠。
如果休眠是在同步代码块中执行,休闲不会让出锁对象。
wait(); //线程等待
notify(); //唤醒线程
线程的优先级:
最大优先级: MAX_PRIORITY 10
最小优先级: MIN_PRIORITY 1
中间优先级: NORM_PRIORITY 5
设置优先级:setPriority();
加入线程
join(); //加入线程
join线程会抢先拿到CPU来执行线程,然后其他的线程再来执行
vield(); //暂停当前正在执行的线程对象,并执行其他线程
-- 当前的线程回到就绪的状态,让出CPU
当前的线程从运行阶段回到就绪阶段,目的是把CPU的资源让给其他的线程
守护线程
守护线程会随着主线程的结束而结束
setDaemon(boolean on) //将该线程标记为守护线程或用户线程
----------------------------------------
网络编程:
TCP和UDP协议:
UDP:将数据源和目的地封装到数据包中,不需要建立连接。
每个数据包的大小限制在64k
因为不建立连接,所以安全性差,速度快
TCP:建立连接形成传输数据的通道,然后再传输数据,通过三次握手
安全性高,效率低
InetAddress类: -- 是用于管理ip的类,没有构造器
1.单例模式
2.根据静态的方法来返回该对象
InetAddress.getlocalhost(); //返回本机主机
ia.getHostAddress(); //返回I地址字符串(以文本表现形式)
ia.getHostName(); //获取此IP地址的主机名
getByName(String host); //在给定主机名的情况下确定主机的IP地址
*******************************
代码:
package cc.chengchengzhang;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class AddressDemo {
public static void main(String[] args) {
//获得本机ip地址
try {
InetAddress ia = InetAddress.getLocalHost();
//获得本机的IP字符串
String ip = ia.getHostAddress();
System.out.println(ip);
//获得主机名
String hostName = ia.getHostName();
System.out.println(hostName);
//根据已经获得的主机名获取IP地址
InetAddress ia1 = ia.getByName("张宜成-PC");
System.out.println(ia1);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
*******************************
UDP的开发步骤
把UDP代码改造成可以从键盘录入数据:
*********************************************************************
服务端:
package com.rl.udp1;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ServerDemo {
public static void main(String[] args) throws IOException {
//创建服务端的套接字对象
DatagramSocket ds = new DatagramSocket(10000);
System.out.println("服务端正在运行....");
while(true){
//接收数据包的字节数组
byte[] bs = new byte[1024];
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length);
//接收
ds.receive(dp);
//解析数据
InetAddress ia = dp.getAddress();
String ip = ia.getHostAddress();
//获得数据的长度
int len = dp.getLength();
//获得数据包中的数据
byte[] bs1 = dp.getData();
String result = new String(bs1, 0, len);
System.out.println("ip地址是:"+ip+" 数据是:"+result);
if("exit".equals(result)){
break;
}
}
//释放资源
ds.close();
}
}
**************************************************************
客户端:
package com.rl.udp1;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建客户端的套接字对象
DatagramSocket ds = new DatagramSocket();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = null;
while((line = br.readLine()) != null){
//准备数据(字节数组的方式)
byte[] bs = line.getBytes();
InetAddress address = InetAddress.getByName("192.168.1.103");
//创建数据包
DatagramPacket dp = new DatagramPacket(bs, bs.length, address, 10000);
//发送数据包
ds.send(dp);
System.out.println("发送了:"+line);
if("exit".equals(line)){
break;
}
}
//释放资源
ds.close();
}
}
**********************************************************
TCP:
开发步骤:
TCP服务端:
1.创建服务器对象,指定端口
ServerSocket(int port) //创建绑定到特定端口的服务器套接字
2.监听并获得客户端的对象socket
Socket s = ss.accept(); //监听并接受到此套接字的连接
3.获得输入流
InputStream is = xxx.getInputStream(); //返回此套接字的输入流
4.读取数据
5.释放资源
TCP客户端:
1.创建客户端socket对象
Socket(String host, int port) //创建一个流套接字并将其连接到指定主机上的指定端口号
2.获得输入流
OutputStream os = xx.getOutputStream(); //返回此套接字的输入流
3.写数据
4.释放资源 ***********************************
代码:
服务端代码:
package com.rl.tcp1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer {
public static void main(String[] args) throws IOException {
//创建服务端的套接字
ServerSocket ss = new ServerSocket(10000);
//监听客户端的请求并且接受客户端的套接字
Socket s = ss.accept();
//获得输入流
InputStream in = s.getInputStream();
//获得输出流
OutputStream out = s.getOutputStream();
//创建高效缓存区字符流
BufferedReader br = new BufferedReader(new InputStreamReader(in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
String line = null;
while((line = br.readLine()) != null){
System.out.println("接收到数据:"+line);
bw.write(line.toUpperCase());
bw.newLine();
bw.flush();
}
bw.close();
br.close();
//释放资源
s.close();
ss.close();
}
}
客户端代码:
package com.rl.tcp1;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClient {
public static void main(String[] args) throws UnknownHostException, IOException {
//创建客户端的套接字
Socket s = new Socket("192.168.1.103", 10000);
//获得输出流
OutputStream out = s.getOutputStream();
InputStream in = s.getInputStream();
//获得从控制台输入的流
BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in));
//服务器端返回的输入流
BufferedReader br = new BufferedReader(new InputStreamReader(in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));
//读取控制台的数据
String line = null;
while((line = br1.readLine()) != null){
if("exit".equals(line)){
break;
}
bw.write(line);
bw.newLine();
bw.flush();
String result = br.readLine();
System.out.println("服务端的反馈数据:"+result);
}
out.close();
s.close();
}
}
***********************************
相关文章
- 暂无相关文章
用户点评