Java基础语法,常用知识复习(4)
上一篇
下一篇
10.泛型(Generic)
10.1泛型的使用
//没有使用泛型
public void test1(){
ArrayList list = new ArrayList();
list.add(80);
list.add(90);
//类型不安全
//list.add("Tom");
for(Object item : list){
//强转时会出现ClassCastException
int val = (Integer)item;
System.out.println(val);
}
}
//使用了泛型后
public void test2(){
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(80);
list.add(90);
//编译时,会进行类型检查,保证数据的安全,编译不通过
//list.add("Tom");
for(Integer item : list){
//不需要强转了
int val = item;
System.out.println(val);
}
Interator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
int val = iterator.next();
System.out.println(val);
}
}
/**
使用泛型的总结
① 集合接口或集合类在jdk5.0时都修改为带泛型的结构。
② 在实例化集合类时,可以指明具体的泛型类型
③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性等)使用到类的泛型的位置,都指定为实例化的泛型类型。比如:add(E e) --->实例化以后:add(Integer e)
④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换
⑤ 如果实例化时,没指明泛型的类型。默认类型为java.lang.Object类型。
*/
10.2自定义泛型的使用
10.2.1 自定义泛型类,泛型方法
public interface MyGeneric<K, V>{
}
public class Order <T> {
int age;
String name;
T t;
T[] arr;
//这个构造器是错误的
public Order<T>(){}
//构造器
public Order(int age, String name, T t){
this.age = age;
this.name = name;
this.t = t;
//编译失败
//T[] arr = new T[10];
//编译正常(运行时T 必须为Object时才可以正常使用,不然会报类型转换错误)
//java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
arr = (T[]) new Object[10];
}
//泛型方法
//[访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
public <E> List<E> copyArrToList(E[] arr){
List<E> list = new ArrayList<E>();
for (E e : arr) {
list.add(e);
}
return list;
}
//以下并不是泛型方法
public T getRealAge(){
return t;
}
public T setRealAge(T t){
T temp = this.t;
this.t = t;
return temp;
}
//static 的方法中不能声明泛型
//public static void show(T t){}
}
//泛型不同的引用不能相互赋值
List<Integer> integerList = new ArrayList<>();
//编译报错
//List<Object> objectList = integerList;
//分析,假如正确
//objectList.add(new Object());
//Integer val = integerList.get(0);//试图把 object赋值给Integer (这是不可能的)
10.2.2 子类的泛型
class Father<T1, T2>{}
//子类不保留父类的泛型
//1)没有类型擦除
class Son1 extends Father{
//等价于 class Son1 extends Father<Object, Object>{}
}
//2)具体类型
class Son2 extends Father<Integer, String>{}
//子类保留父类的泛型
//1)全部保留
class Son3<T1, T2> extends Father<T1, T2>{}
//2)部分保留
class Son4<T2> extends Father<Integer, T2>{}
10.2.3 泛型方法
// [访问权限] <泛型> 返回类型 方法名([泛型标识 参数名称]) 抛出的异常
//public <T extends Comparable<? super T>> void sort(List<T> list){}
//表示T必须实现Comparable接口并且 接口的泛型 必须是[T,无穷大)
public static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
for (T o : a) {
c.add(o);
}
}
public static <T> void fromArrayToCollection(Collection<T> c,T[] a) {
for (T o : a) {
c.add(o);
}
}
public static void main(String[] args) {
Object[] ao = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(ao, co);
String[] sa = new String[20];
Collection<String> cs = new ArrayList<>();
fromArrayToCollection(sa, cs);
Collection<Double> cd = new ArrayList<>();
// 下面代码中T是Double类,但sa是String类型,编译错误。
// fromArrayToCollection(sa, cd);
// 下面代码中T是Object类型,sa是String类型,可以赋值成功。
fromArrayToCollection(sa, co);
fromArrayToCollection(co, sa);
System.out.println(co);
}
10.2.4 泛型在继承上的体现
/**
如果B是A的一个子类型(子类或者子接口),而G是具有泛型声明的
类或接口,G<B>并不是G<A>的子类型!
比如:String是Object的子类,但是List<String >并不是List<Object>
的子类
*/
class Creature{}
class Person extends Creature{}
class Man extends Person{}
class PersonTest {
//T可以是Person及其子类
public static <T extends Person> void test(T t){
System.out.println(t);
}
public static void main(String[] args) {
test(new Person());
test(new Man());
//The method test(T) in the type PersonTest is not
//applicable for the arguments (Creature)
//test(new Creature());//编译失败
}
//对比集合
public void testGenericAndSubClass() {
Person[] persons = null;
Man[] mans = new Man[10];
// 而 Person[] 是 Man[] 的父类.
persons = mans;
Person p = mans[0];
//编译通过但是运行会失败
persons[2] = new Person();
System.out.println(mans[2]);
// 在泛型的集合上
List<Person> personList = null;
List<Man> manList = null;
//personList = manList;(报错)
}
}
10.2.5 通配符: ? 的使用
/**
1.使用类型通配符:?
比如:List<?> ,Map<?,?>
List<?>是List<String>、List<Object>等各种泛型List的父类。
2.读取List<?>的对象list中的元素时,永远是安全的,因为不管list的真实类型是什么,它包含的都是Object。
3.写入list中的元素时,不行。因为我们不知道c的元素类型,我们不能向其中添加对象。
唯一的例外的是null,它是所有类型的成员。
另一方面,我们可以调用get()方法并使用其返回值。返回值是一个未知的类型,但是我们知道,它总是一个Object
4.有限制的通配符
<? extends Person> (无穷小 Person]
<? super Person> [Person,无穷大)
<? extends Comparable> 只允许泛型为实现Comparable接口的实现类的引用调用
*/
public static void main(String[] args) {
List<?> list = null;
list = new ArrayList<String>();
list = new ArrayList<Double>();
//将任意元素加入到其中不是类型安全的:
//list.add(3);//编译不通过
list.add(null);
List<String> stringList = new ArrayList<>();
List<Integer> integerList = new ArrayList<>();
stringList.add("AA");
stringList.add("BB");
stringList.add("CC");
integerList.add(12);
integerList.add(19);
integerList.add(20);
read(stringList);
read(integerList);
}
public static void read(List<?> list){
for (Object o : list) {
System.out.println(o);
}
}
public static <T> void test(T t,ArrayList<T> list){}
//1.编译错误:不能用在泛型方法声明上,返回值类型前面<>不能使用?
//public static <?> void test(? t,ArrayList<?> list){}
//2.编译错误:不能用在创建对象上,右边属于创建集合对象
//ArrayList<?> list2 = new ArrayList<?>();
//3.编译错误:不能用在泛型类的声明上
//class GenericTypeClass<?>{}//:编译错误:不能用在泛型类的声明上
//有限制的通配符
public static void printCollection(Collection<? extends Person> coll){
Iterator<? extends Person> iterator = coll.iterator();
while(iterator.hasNext()){
//可以是[Person,无穷)
Person next = iterator.next();
System.out.println(next);
}
//编译报错,coll的泛型可能是更小的
//coll.add(new Person());
}
public static void printCollection2(Collection<? super Person> coll){
Iterator<? super Person> iterator = coll.iterator();
while(iterator.hasNext()){
//只能是Object
Object next = iterator.next();
System.out.println(next);
}
//可以添加数据 (无穷小,Person]
coll.add(new Person());
coll.add(new Man());
}
//泛型嵌套
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
10.2.5 泛型的例题
/**
开发一个泛型Apple类,要求有一个重量属性weight在测试类中实例化不同的泛型对象,要求对象对象a1的这一属性是Integer型,a2的这一属性是Double型。
分别为a1,a2,a3的重量属性赋值为:500,500.0,在测试类中通过对象调用访问器得到属性值并输出。
*/
public class Apple<T extends Number> {
private T weight;
public Apple (T weight){
this.weight = weight;
}
public T getWeight(){
return weight;
}
public void setWeight(T weight){
this.weight = weight;
}
}
class TestApple{
public static void main(String[] args) {
Apple<Integer> integerApple = new Apple<>(500);
Apple<Double> doubleApple = new Apple<>(500.0);
System.out.println(integerApple.getWeight());
System.out.println(doubleApple.getWeight());
}
}
/************************************************************************************/
/**
定义个泛型类 DAO<T>,在其中定义一个 Map 成员变量,Map 的键
为 String 类型,值为 T 类型。
分别创建以下方法:
public void save(String id,T entity): 保存 T 类型的对象到 Map 成员
变量中
public T get(String id):从 map 中获取 id 对应的对象
public void update(String id,T entity):替换 map 中 key 为 id 的内容,
改为 entity 对象
public List<T> list():返回 map 中存放的所有 T 对象
public void delete(String id):删除指定 id 对象
定义一个 User 类:
该类包含:private 成员变量(int 类型) id,age;(String 类型)name。
定义一个测试类:
创建 DAO 类的对象, 分别调用其 save、get、update、list、delete 方
法来操作 User 对象,
使用 Junit 单元测试类进行测试。
*/
class TestDao{
public static void main(String[] args) {
Dao<Users> usersDao = new Dao<>();
usersDao.save("zhangsan",new Users("zhangsan",13));
usersDao.save("lisi",new Users("lisi",29));
usersDao.save("wangwu",new Users("wangwu",19));
usersDao.save("tom", new Users("tom", 23));
List<Users> list = usersDao.list();
printList(list);
usersDao.delete("zhangsan");
System.out.println(usersDao.getSize());
System.out.println(usersDao.get("lisi"));
}
public static void printList(List<?> list){
for (Object o : list) {
System.out.println(o);
}
}
}
class Dao<T>{
Map<String, T> map = new HashMap<>();
public void save(String id,T entity){
if (map.containsKey(id)){
throw new RuntimeException("该数据已存在");
}
map.put(id, entity);
}
public T get(String id){
return map.get(id);
}
public void update(String id,T entity){
if (map.containsKey(id)){
map.put(id, entity);
}
throw new RuntimeException("数据不存在");
}
//返回 map 中存放的所有 T 对象s
public List<T> list(){
List<T> list = new ArrayList<>();
//Set<Map.Entry<String, T>> entries = map.entrySet();
// for (Map.Entry<String, T> entry : entries) {
// System.out.println(entry.getKey() + " = " + entry.getValue());
// }
Collection<T> values = map.values();
for (T value : values) {
list.add(value);
}
return list;
}
public void delete(String id){
if (map.containsKey(id)){
map.remove(id);
}
}
public int getSize(){
return map.size();
}
}
class Users{
private String name;
private int age;
public Users(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Users{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Users users = (Users) o;
if (age != users.age) return false;
return name != null ? name.equals(users.name) : users.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
11.IO
11.1 File类
1. File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
2.File类声明在java.io包下
3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用IO流来完成。
4. 后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的"终点".
5.实例化
File(String filePath)
File(String parentPath,String childPath)
File(File parentFile,String childPath)
路径的分类
相对路径:相较于某个路径下,指明的路径。
绝对路径:包含盘符在内的文件或文件目录的路径
6.常用的方法
boolean canExecute() //是否可执行
boolean canRead()//是否能读
boolean canWrite() //是否能写
boolean isFile()//是否是文件
boolean isDirectory();//是否是文件目录
boolean exists() //判断是否存在
boolean createNewFile()//创建文件 如果存在,则不创建 返回false
boolean mkdir()//创建文件目录 存在就不创建了, 如果上层目录不存在则不创建
boolean mkdirs()//创建文件目录 如果上层文件不存在,一并创建
boolean delete()//删除文件或目录, 目录有文件则不删除 删除不走回收站
/**
输出某个文件夹下的所有文件
*/
public static void printFileName(File file){
if (file.isFile()){
System.out.println(file);
}else {
File[] files = file.listFiles();
for (File f : files) {
printFileName(f);
}
}
}
11.2 IO流的概述
1.流的分类
①.操作数据单位:字节流,字符流
②.数据的流向:输入流,输出流
③.流的角色:节点流,处理流
2.输入、输出的标准化过程
2.1 输入过程
① 创建File类的对象,指明读取的数据的来源。(要求此文件一定要存在)
② 创建相应的输入流,将File类的对象作为参数,传入流的构造器中
③ 具体的读入过程:
创建相应的byte[] 或 char[]。
④ 关闭流资源
说明:程序中出现的异常需要使用try-catch-finally处理。
2.2 输出过程
① 创建File类的对象,指明写出的数据的位置。(不要求此文件一定要存在)
② 创建相应的输出流,将File类的对象作为参数,传入流的构造器中 此时会创建文件
③ 具体的写出过程:
write(char[]/byte[] buffer,0,len)
④ 关闭流资源
说明:程序中出现的异常需要使用try-catch-finally处理。
流的体系结构
抽象基类 节点流(或文件流) 缓冲流(处理流的一种)
InputStream FileInputStream (read(byte[] buffer)) BufferedInputStream (read(byte[] buffer))
OutputStream FileOutputStream (write(byte[] buffer,0,len) BufferedOutputStream (write(byte[] buffer,0,len) / flush()
Reader FileReader (read(char[] cbuf)) BufferedReader (read(char[] cbuf) / readLine())
Writer FileWriter (write(char[] cbuf,0,len) BufferedWriter (write(char[] cbuf,0,len) / flush()

11.3 节点流(文件流)的示例代码
/**
FileReader/FileWriter/FileOutputStream/FileInputStream
读入的文件一定要存在,否则就会报FileNotFoundException。
*/
public static void testFileReaderAndFileWriter(){
FileWriter fileWriter = null;
FileReader fileReader = null;
try {
//创建流
fileWriter = new FileWriter(new File("java_base4" + File.separator + "copy.txt"));
fileReader = new FileReader(new File("java_base4" + File.separator + "hello.txt"));
char[] c = new char[3];
int temp = -1;
//读加写
while ((temp = fileReader.read(c)) != -1){
fileWriter.write(c, 0 ,temp);
}
//刷新
fileWriter.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
if (fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fileWriter != null){
try {
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void testFileInputStreamAndFileOutputStream(){
long start = System.currentTimeMillis();
FileInputStream fis = null;
FileOutputStream fos = null;
try {
fis = new FileInputStream("java_base4" + File.separator + "test.jpg");
fos = new FileOutputStream("java_base4" + File.separator + "test_bak.jpg");
int temp = -1;
byte[] b = new byte[10];
while ((temp = fis.read(b)) != -1){
fos.write(b, 0, temp);
}
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
System.out.println("用时:" + (end -start));
}
11.4 缓冲流的示例代码
/**
* 1.缓冲流:
* BufferedInputStream
* BufferedOutputStream
* BufferedReader
* BufferedWriter
* 2.作用:提供流的读取、写入的速度
* 提高读写速度的原因:内部提供了一个缓冲区
*
* 3. 处理流,就是“套接”在已有的流的基础上。
*/
public static void testBufferedReaderAndBufferedWriter(){
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new FileReader("java_base4" + File.separator + "hello.txt"));
bw = new BufferedWriter(new FileWriter("java_base4" + File.separator + "copy.txt",true));
String s = null;
while ((s = br.readLine()) != null){
bw.write(s);
bw.newLine();
}
bw.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(bw != null){
try {
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void testBufferedInputStreamAndBufferedOutputStream(){
long start = System.currentTimeMillis();
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
bis = new BufferedInputStream(new FileInputStream("java_base4" + File.separator + "test.jpg"));
bos = new BufferedOutputStream(new FileOutputStream("java_base4" + File.separator + "test_bak_x.jpg"));
byte[] bytes = new byte[10];
int temp = -1;
while ((temp = bis.read(bytes)) != -1){
bos.write(bytes, 0, temp);
}
bos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(bis != null){
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bos != null){
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
long end = System.currentTimeMillis();
System.out.println("X用时:" + (end -start));
}
11.5 转换流的示例代码
/**
* 处理流之二:转换流的使用
* 1.转换流:属于字符流
* InputStreamReader:将一个字节的输入流转换为字符的输入流
* OutputStreamWriter:将一个字节的输出流转换为字符的输出流
* 2.作用:提供字节流与字符流之间的转换
* 3. 解码:字节、字节数组 --->字符数组、字符串
* 编码:字符数组、字符串 ---> 字节、字节数组
*
*
*/
//读写相关的应用
public void test2() throws Exception {
//1.造文件、造流
File file1 = new File("dbcp.txt");
File file2 = new File("dbcp_gbk.txt");
FileInputStream fis = new FileInputStream(file1);
FileOutputStream fos = new FileOutputStream(file2);
InputStreamReader isr = new InputStreamReader(fis,"utf-8");
OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");
//2.读写过程
char[] cbuf = new char[20];
int len;
while((len = isr.read(cbuf)) != -1){
osw.write(cbuf,0,len);
}
//3.关闭资源
isr.close();
osw.close();
}
//转换流,缓冲流,标准输入流的应用
public class MyScanner {
public static void main(String[] args) {
MyScanner myScanner = new MyScanner(System.in);
String s = myScanner.readString();
System.out.println(s);
}
BufferedReader br = null;
MyScanner(InputStream inputStream){
InputStreamReader reader = new InputStreamReader(inputStream);
br = new BufferedReader(reader);
}
public String readString() {
// Declare and initialize the string
String string = "";
// Get the string from the keyboard
try {
string = br.readLine();
} catch (IOException ex) {
System.out.println(ex);
}
// Return the string obtained from the keyboard
return string;
}
// Read an int value from the keyboard
public int readInt() {
return Integer.parseInt(readString());
}
// Read a double value from the keyboard
public double readDouble() {
return Double.parseDouble(readString());
}
// Read a byte value from the keyboard
public double readByte() {
return Byte.parseByte(readString());
}
// Read a short value from the keyboard
public double readShort() {
return Short.parseShort(readString());
}
// Read a long value from the keyboard
public double readLong() {
return Long.parseLong(readString());
}
// Read a float value from the keyboard
public double readFloat() {
return Float.parseFloat(readString());
}
public void close() throws IOException {
if (br != null){
br.close();
}
}
}
11.5 其他流
/**
* 其他流的使用
* 1.标准的输入、输出流
* System.in(默认从键盘输入) System.out(默认从控制台输出)
* System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流
* 2.打印流 PrintStream 和PrintWriter
* 3.数据流 DataInputStream 和 DataOutputStream
*/
/*
1.3练习:
从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
直至当输入“e”或者“exit”时,退出程序。
方法一:使用Scanner实现,调用next()返回一个字符串
方法二:使用System.in实现。System.in ---> 转换流 ---> BufferedReader的readLine()
*/
public static void main(String[] args) {
//System.setIn();
System.out.println("开始输入你的文章:");
PrintStream ps = null;
MyScanner my = null;
try {
//打印流
//ps = new PrintStream("java_base4\\小说.txt");
// 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
ps = new PrintStream(new FileOutputStream("java_base4\\小说.txt"),true);
//重置打印流
System.setOut(ps);
//读取键盘输入的内容
my = new MyScanner(System.in);
while (true){
String s = my.readString();
if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)){
break;
}
System.out.println(s);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (ps != null){
ps.close();
}
if (my != null){
try {
my.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//数据流的使用
//将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
//注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
public static void testDataStream() throws Exception{
FileOutputStream fos = new FileOutputStream("java_base4\\my.dat");//文件已经创建好了
FileInputStream fis = new FileInputStream("java_base4\\my.dat");
DataInputStream dis = new DataInputStream(fis);
DataOutputStream dos = new DataOutputStream(fos);
dos.writeBoolean(true);
dos.writeUTF("果冻");
dos.writeInt(18);
dos.writeFloat(10.0f);
dos.flush();
boolean b = dis.readBoolean();
String name = dis.readUTF();
int age = dis.readInt();
float v = dis.readFloat();
System.out.println("性别 : " + b);
System.out.println("姓名 : " + name);
System.out.println("年龄 : " + age);
System.out.println("浮点数 : " + v);
dos.close();
dis.close();
}
11.6 对象流 ObjectInputStream/ObjectOutputStream
1.作用:
ObjectOutputStream:内存中的对象--->存储中的文件、通过网络传输出去:序列化过程
ObjectInputStream:存储中的文件、通过网络接收过来 --->内存中的对象:反序列化过程
2.对象的序列化机制:
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘
上,或通过网络将这种二进制流传输到另一个网络节点。//当其它程序获取了这种二进制流,就可以恢复成原来的
Java对象
//代码示例
public class ObjectStream {
public static void main(String[] args) throws Exception{
testObjectStream();
}
public static void testObjectStream () throws Exception{
//ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("java_base4\\object.dat"));
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("java_base4\\object.dat"));
//oos.writeObject(new Person("张三", 18, "我是个学生"));
//oos.close();
Object o = ois.readObject();
System.out.println(o);
ois.close();
}
}
/**
* Person需要满足如下的要求,方可序列化
* 1.需要实现接口:Serializable
* 2.当前类提供一个全局常量:serialVersionUID 不提供的化 每次编译都会随机默认一个serialVersionUID 的值 反序列化时 就会失败
* 3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性
* 也必须是可序列化的。(默认情况下,基本数据类型可序列化)
*
*
* 补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量
*/
class Person implements Serializable {
private static final long serialVersionUID = 1L;
public Person(String name, int age, String content) {
this.name = name;
this.age = age;
this.content = content;
}
private String name;
private int age;
private transient String content;//transient 短暂的 不能被序列化
static Double debal;//静态变量不能被序列化
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", content='" + content + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
11.7 随机存取文件流:RandomAccessFile
/**
* 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
* 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
*
* 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
* 如果写出到的文件存在,则会对原文件内容进行覆盖。(默认情况下,从头覆盖)
*
* 4. 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果。seek(int pos)
*/
public class RandomAccessFileTest {
public static void main(String[] args) {
insterValue(6,"xyz");
}
public static void insterValue(int index, String context){
RandomAccessFile rafInput = null;
ByteArrayOutputStream outputStream = null;
try {
rafInput = new RandomAccessFile("java_base4\\hello.txt", "rw");
rafInput.seek(index);
byte[] b = new byte[5];
int temp = -1;
//StringBuilder sb = new StringBuilder(context);
outputStream = new ByteArrayOutputStream();
while ((temp = rafInput.read(b)) != -1){
//sb.append(new String(b, 0, temp));
outputStream.write(b, 0 ,temp);
}
outputStream.flush();
//重置指针
rafInput.seek(index);
rafInput.write(context.getBytes());
rafInput.write(outputStream.toByteArray());
//rafInput.write(sb.toString().getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
if (rafInput != null){
try {
rafInput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
12. 网络编程
12.1 InetAddress类的使用
一、实现网络通信需要解决的两个问题
1.如何准确地定位网络上一台或多台主机;定位主机上的特定的应用
2.找到主机后如何可靠高效地进行数据传输
二、网络通讯的两个要素
1.对应问题一: IP 和端口号
2.对应问题二:提供网络通讯协议: UCP/IP参考模型(应用层、传输层、网络层、物理+数据链路层)
三、通信要素一:IP和端口号
1.IP的理解
1). IP:唯一的标识 Internet 上的计算机(通信实体)
2). 在Java中使用InetAddress类代表IP(此类的一个对象就代表着一个具体的IP地址)
3). IP分类:IPv4 和 IPv6 ; 万维网 和 局域网
4). 域名: www.baidu.com www.mi.com www.sina.com www.jd.com
域名解析:域名容易记忆,当在连接网络时输入一个主机的域名后,域名服务器(DNS)负责将域名转化成IP地址,这样才能和主机建立连接。 -------域名解析
5).本地回路地址 127.0.0.1对应着:localhost
2.
实例化:InetAddress.getByName(),InetAddress.getLocalHost()
常用方法: getHostNaem(); getHostAddress();
3.端口号
* 要求:不同的进程不同的端口号
* 范围:被规定为一个 16 位的整数 0~65535。
端口号与IP地址的组合得出一个网络套接字:Socket
四、通信要素二:网络通信协议
见下图
- 分型模型
![image]()
2.TCP和UDP的区别
![image]()
3.TCP三次握手和四次挥手
![image]()
![image]()
//代码示例
public static void main(String[] args) {
try {
InetAddress inet1 = InetAddress.getByName("192.168.10.14");
System.out.println(inet1);// /192.168.10.14
InetAddress inet2 = InetAddress.getByName("mobdev.dhcccloud.com.cn");//mobdev.dhcccloud.com.cn/60.171.122.223
InetAddress inet5 = InetAddress.getByName("test.dhcccloud.com.cn");//test.dhcccloud.com.cn/60.171.122.223
System.out.println("--------------" + inet2);
System.out.println("--------------" + inet5);
InetAddress inet3 = InetAddress.getByName("localhost");
System.out.println(inet3);
//获取本地ip
InetAddress inet4 = InetAddress.getLocalHost();
System.out.println(inet4);
//getHostName()
System.out.println("hostname" + inet2.getHostName());
//getHostAddress()
System.out.println("hostaddress" + inet2.getHostAddress());
} catch (UnknownHostException e) {
e.printStackTrace();
} finally {
}
}
12.2 TCP网络编程 示例代码
public class TpcTest {
//客户端
@Test
public void client(){
Socket socket = null;
OutputStream outputStream = null;
BufferedInputStream bufferedInputStream = null;
BufferedInputStream inputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
//连接服务端Socket
socket = new Socket("localhost", 9999);
outputStream = socket.getOutputStream();
bufferedInputStream = new BufferedInputStream(new FileInputStream("test.jpg"));
byte[] buffb = new byte[1024];
int temp = -1;
while ((temp = bufferedInputStream.read(buffb)) != -1){
outputStream.write(buffb, 0, temp);
}
outputStream.flush();
//给服务器说停止本次传输了
socket.shutdownOutput();
//获取输入流,读取服务器端返回消息
inputStream = new BufferedInputStream(socket.getInputStream());
//使用byteArrayOutputStream 流来接收,防止控制台打印时乱码
byteArrayOutputStream = new ByteArrayOutputStream();
while ((temp = inputStream.read(buffb)) != -1){
byteArrayOutputStream.write(buffb, 0, temp);
}
byteArrayOutputStream.flush();
System.out.println(new String(byteArrayOutputStream.toByteArray()));
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if(byteArrayOutputStream != null){
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedInputStream != null){
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//服务器端
@Test
public void service(){
Socket socket = null;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
BufferedOutputStream outputStream = null;
try {
//创建服务端ServerScoket
ServerSocket serverSocket = new ServerSocket(9999);
//获取连接
socket = serverSocket.accept();
//获取输入流
bufferedInputStream = new BufferedInputStream(socket.getInputStream());
//本地输出流
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("hhh.jpg"));
byte[] buffb = new byte[1024];
int temp = -1;
//通过输入流读取数据并下载到本地
while ((temp = bufferedInputStream.read(buffb)) != -1){
bufferedOutputStream.write(buffb, 0, temp);
}
bufferedOutputStream.flush();
//返回消息
outputStream = new BufferedOutputStream(socket.getOutputStream());
String message = "你好图片已接受到";
outputStream.write(message.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedInputStream != null){
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedOutputStream != null){
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket != null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
12.3 UDP网络编程 示例代码
public class UDPTest {
@Test
public void client(){
DatagramSocket socket = null;
try {
socket = new DatagramSocket();
String content = "我是发送的内容,短信轰炸!!!";
//组包
InetAddress localhost = InetAddress.getByName("localhost");
DatagramPacket packet = new DatagramPacket(content.getBytes(), 0, content.getBytes().length, localhost, 9999);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
} finally {
//socket.disconnect();
if(socket != null)
socket.close();
}
}
@Test
public void service(){
DatagramSocket socket = null;
try {
socket = new DatagramSocket(9999);
byte[] buffer = new byte[200];//要确保数据可以放下
DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length);
//接收消息
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null)
socket.close();
}
}
}
12.4 URL网络编程
/**
* 1.URL:统一资源定位符,对应着互联网的某一资源地址
* 2.格式:
* http://localhost:8080/examples/beauty.jpg?username=Tom
* 协议 主机名 端口号 资源地址 参数列表
* 3.实例化URL
* URL url = new URL(http://localhost:8080/examples/beauty.jpg?username=Tom);
* 4.常用的方法
* public String getProtocol();//获取协议 http
* public String getHost();// 获取主机名 localhost
* public String getPort();//获取端口 8080
* public String getPath();//获取文件路径 /examples/beauty.jpg
* public String getFile();//获取文件名 /examples/beauty.jpg?username=Tom
* public String getQuery();//获取查询名 username=Tom
*/
public void test(){
HttpURLConnection urlConnection = null;
InputStream inputStream = null;
BufferedOutputStream outputStream = null;
try {
//创建URL对象
URL url = new URL("https://q-extra.paixin.com/default/2021/0305/7c2a435bc69e61d62124b1fc4d28caeb.jpg");
//打开连接
urlConnection = (HttpURLConnection) url.openConnection();
//连接
urlConnection.connect();
//获取输入流
inputStream = urlConnection.getInputStream();
//获取文件
String file = url.getFile();// /default/2021/0305/7c2a435bc69e61d62124b1fc4d28caeb.jpg
String[] split = file.split("\\.");
outputStream = new BufferedOutputStream(new FileOutputStream("aaa." + split[1]));
int temp = -1;
byte[] bytes = new byte[1024];
//开始下载文件
while ((temp = inputStream.read(bytes)) != -1){
outputStream.write(bytes,0, temp);
}
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭资源
if(outputStream != null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream != null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(urlConnection != null){
urlConnection.disconnect();
}
}
}





浙公网安备 33010602011771号