chapter 3. java语言基础

一、面向对象

概念: java 使用面向对象范式,包含了封装,继承和多态。这意味着java程序的基本构造块是对象类。
对象代表现实世界中的事物或一些问题领域的事物。
对象(也成为实例)有以下特点:
对象具有属性attribute和行为behavior/method。
对象具有变化的状态。
对象具有unique id。
对象都是某个类别的实例。

二、 数据类型

基本数据类型和引用数据类型
基本数据类型和引用数据类型

Generic class

在这里插入图片描述
在这里插入图片描述

generic method

在这里插入图片描述

e.g.
在这里插入图片描述

1. 基本数据类型primitive types

存储位置:存储在中的
传递方式:调用方法时作为参数是按数值传递的
常见:byte,short,int,long,float,double,char,boolean等

2. 引用数据类型object types

存储位置:存放在中的,而栈中存放的是其具体内容所在内存的地址
传递方式:调用方法时作为参数是按引用传递的,传递的是引用的副本 reference
常见:字符串型String、类、 接口类型、 数组类型、 枚举类型、 注解类型。
存储方式

三、自动转换/强制转换 和 装箱/拆箱

1. 自动转换

概念:大=小,自动转
按照字节数排序大小:
byte(1) 、short(2)、char(2) < int(4) < float(4) < long(8) < double(8)

4个同学去有4张床位的寝室和去有8张床位的寝室,都能很好的容纳;
8个同学去有8张床位的寝室,没有问题;
8个同学去仅有4张床位的寝室就容纳不下了。

int i = 1;
byte b = 2;
int j = b + i;
// 大 = 小;

2. 强制转换

概念:小=大,需要强制转换
syntax: 数据类型 变量名 = (数据类型) 被转数据值;

int i = (int)1.5;

3. 装箱和拆箱(Autoboxing and unboxing)

装箱:自动将基本数据类型转换为包装器类型;(简写 Integer.valueOf(int i) )
拆箱:自动将包装器类型转换为基本数据类型。(简写 int a= k.intValue(){return value})

为什么要用integer类:
Integer对应是int类型的包装类,就是把int类型包装成Object对象

  1. 方便在各种类型间转化,通过各种方法的调用。
  2. 泛型使用,例如集合的泛型,List,如果写List会报错。
int i = 5;
//自动装箱:简写Integer g = Integer.valueOf(int i) 
Integer g = i


Integer k = new Integer(500);
//自动拆箱:简写int a = k.intValue(){return value}
int n = k;

数据类型对应的包装器类:
Autoboxing and unboxing

四、值传递/引用传递

java内的基础类型数据传递都是值传递, java中实例对象的传递是引用传递。
对值传递进行修改是直接修改,对引用传递进行修改,只会创建一个新地址值,原来的地址值不会改变。(stringbuilder 和stringbuffer可以改变字符串,而不是创一个新的地址值)

五、String 类

1. 概念

java.lang.String 类即 字符串。 String类中包括用于检查各个字符串的方法,比如 比较、提取、搜索以及创建具有翻译为大小写的所有字符的字符串的副本。

2. 特点:

  1. 字符串不变:字符串在创建之后不可改变。
  2. 可被共享,使用字符串时,只是复制它的地址值。

string类为什么要是final修饰的
1 被final修饰的类,不可以被继承,所以不会别其它类改变,这样会更加的安全.
2 string是共享在常量池中的,String str=“abc”, char data[] = {‘a’, ‘b’, ‘c’};是等价的,他们都放在了字符串常量池中.

3. 常用方法:

3.1. 比较

boolean equals (obect obj):将此字符串于指定字符串进行比较。
boolean equalsIgnoreCase(String str):将此字符串于指定字符串进行比较(忽略大小写)。

3.2. 提取

int length():返回字符串长度
String concat(String str):在末尾连接指定字符串
char charAt(int index):返回指定索引处的char值
int indexOf(String str):返回指定字符串第一次出现的索引值
int lastIndexOf(char ch):返回指定字符串最后一次出现的索引位置
String substring(int beginIndex):返回一串字符串,从该索引开始截取到字符串结束
String substring(int beginIndex, int endIndex):返回一串字符串,从开始索引到结束索引截取字符串,包含开始索引但不包括结束索引。

我的题解 - 字符串最后一个单词的长度#牛客华为机考:

lastIndexOf(char ch)
https://blog.nowcoder.net/n/524fe4afb3cf4e26bccee141a2c19837

我的题解 计算某字母出现次数:

substring(int beginIndex, int endIndex),equalsIgnoreCase(String str)
https://blog.nowcoder.net/n/8a85d68aaa6845589d397448c7655358

int upCase = 0;
int lowCase = 0;
int num = 0;
string str = "Builder";
for(int i = 0; i < str.length; i++)
{
	char ch = str.charAt(i);
	if(ch>='A' && ch <= 'Z')
		upCase++;
	else if (ch >= 'a' && ch <= 'z')
		lowCase++;
	else if (ch >= '0' && ch <= '9')
		num++;
	else
		sop("该字符" + ch + "是其他字符")}

3.3. 转换

char[ ] toCharArray():将此字符串转为新的char[ ]字符数组
byte[ ] toBytes():使用平台默认字符集,将此字符串编码转为新的byte[ ]字节数组
String replace(CharSequence target, CharSequence replacement):将target匹配的字符串使用replacement字符串替换。(CharSequence 是一个接口,也是引用类型,作为参数类型可以把string对象传递到方法中)

//String replace(CharSequence target, CharSequence replacement)
String str = "itcast itfaculty";
String replace = str.replace("it", "IT");//ITcast ITfaculty

3.4. 分割

String[ ] split(String regex):按照此字符串给定的regex(规则)拆分为字符串数组。

我的题解:句子逆序(牛客)

split(String regex)
https://www.nowcoder.com/practice/48b3cb4e3c694d9da5526e6255bb73c3?tpId=37&&tqId=21236&rp=1&ru=/ta/huawei/&qru=/ta/huawei/question-ranking

String str = "aa|bb|cc|d";
String[] spl = str.split("|");//{"aa" "bb" "cc" "d"}

六、关键字(final、static、super、this、transient等)

1. static

调用方式

被static 修饰的变量和成员方法属于类的,而不是单独属于某个对象。不可以靠创建对象来调用,只可用类调用:类名.静态方法名(参数) / 类名.类变量名

静态方法:被static修饰的成员方法叫做静态方法。调用:类名.方法名

注意

  1. 静态方法可省略[public]
  2. 静态方法可以直接访问类变量和静态方法
    (优先于对象存在,所以可以被所有对象共享)
  3. 静态方法不能直接访问普通成员变量和方法。反之,成员方法可以直接访问类变量和静态方法
  4. 静态方法中不可用this关键字
  5. 静态方法只能访问静态成员

静态代码块:

格式:static{ //执行语句; }
位置:类中方法外
执行:随着类的加载而(只)执行一次,优先于main方法和构造方法。

2. final

  1. 修饰类 public final class 类名{// }
    不可继承,无子类!不可override!@override的作用:被该注释修饰的方法必须重写父类方法
  2. 修饰方法:modified final Rtype name(参数) {// }
    abstract 和 final 不可同时用
  3. 修饰成员变量
    要么直接赋值,要么构造赋值。
  4. 修饰局部变量
    一旦赋值,基本类型数据不可变,引用类型地址不可变(但值可变)。

static final修饰的一个int 进行修改后是否需要进行重新编译
需要,最好重新编译整个应用来刷新常量引用。https://blog.csdn.net/yunzhonghefei/article/details/89093313
如果修改了这个static修饰的常量类,那么所有引用过这个常量的地方都要更新到服务器。
把静态常量相关的所有class都更新才能生效;最好的方法就是整个war更新项目

3. super

super:代表父类的存储空间表示(可以理解为父亲的引用)
三种用法:

  1. 在子类成员方法中,访问父类成员变量。 e.g. super.成员变量 —父类的
  2. 在子类成员方法中,访问父类成员方法。 e.g. super.成员方法名() —父类的
  3. 在子类构造方法中,访问父类构造方法。 e.g. super(…) —父类的

4. this

this: 代表当前对象的引用(谁调用就代表谁)
三种用法:

  1. 在本类成员方法中,访问本类成员变量。 e.g. this.成员变量 —本类的
  2. 在本类成员方法中,访问本类成员方法。 e.g. this.成员方法名() —本类的
  3. 在本类构造方法中,访问本类构造方法。 e.g. this(…) —本类的

super 和 this

  1. 父类空间优先于子类对象产生。super > this
  2. super和this都必须在构造方法的第一行,所以不能同时出现。

5. transient

概念:被transient修饰的变量不参与序列化和反序列化。当一个对象被序列化的时候,transient型变量的值不包括在序列化的表示中,然而非transient型的变量是被包括进去的。

transient是短暂的意思。对于transient 修饰的成员变量,在类的实例对象的序列化处理过程中会被忽略。 因此,transient变量不会贯穿对象的序列化和反序列化,生命周期仅存于调用者的内存中而不会写到磁盘里进行持久化。

(1)序列化

Java中对象的序列化指的是将对象转换成以字节序列的形式来表示,这些字节序列包含了对象的数据和信息,一个序列化后的对象可以被写到数据库或文件中,也可用于网络传输。一般地,当我们使用缓存cache(内存空间不够有可能会本地存储到硬盘)或远程调用rpc(网络传输)的时候,经常需要让实体类实现Serializable接口,目的就是为了让其可序列化。当然,序列化后的最终目的是为了反序列化,恢复成原先的Java对象实例。所以序列化后的字节序列都是可以恢复成Java对象的,这个过程就是反序列化。

(2)为什么要用transient关键字?

在持久化对象时,对于一些特殊的数据成员(如用户的密码,银行卡号等),我们不想用序列化机制来保存它。为了在一个特定对象的一个成员变量上关闭序列化,可以在这个成员变量前加上关键字transient。

(3)transient的作用

transient是Java语言的关键字,用来表示一个成员变量不是该对象序列化的一部分。当一个对象被序列化的时候,transient型变量的值不包括在序列化的结果中。而非transient型的变量是被包括进去的。 注意static修饰的静态变量天然就是不可序列化的。
————————————————————————————————————
版权声明:本文为CSDN博主「老鼠只爱大米」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上以上transient概念原文出处链接及本声明。
原文链接:https://blog.csdn.net/u012723673/article/details/80699029

一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关心具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。

java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

七、抽象类/接口,多态

1. 抽象类abstract

当父类方法不确定如何进行方法实现时,那这就是一个抽象方法。
抽象方法必须在抽象类中
syntax:
public abstract class Name1
{
public abstract RType name( );
}

  1. 不能直接创建抽象类对象
  2. 必须用一个子类来继承抽象父类
  3. 子类必须覆盖重写抽象类父类当中的所有抽象方法(除非子类也是抽象类)。
  4. 在抽象类中不一定包含抽象方法,但抽象方法必在抽象类中。
  5. 重写override:在子类 去掉abstract关键字,并补上大括号和方法体。
    public class Name2 extends Name1
    {
    @override
    public RType name()
    {
    sop(xxx);
    }
    }

2. 接口 Interface

只要符合接口规范,各种设备都能用。接口就是多个类的公共规范。接口是引用数据类型,最重要的内容是抽象方法。
As long as the interface specification is met, all kinds of equipment can be used.
An interface is a common specification for multiple classes.
the most important content of interface is abstract methods.

syntax:
[public] interface Name
{
//方法体
}
接口包括的内容有:

  1. 常量:[public static final] RType variable,
  2. 抽象方法 [public] [abstract] RType name( ){//}
  3. 默认方法 [public] default RType name( ){//}
  4. 静态方法 public static RType name( ){//}
  5. 私有方法(私有&静态私有)

注意事项

  1. 接口的抽象方法,修饰符必须是固定的两个关键字。(这俩关键字可以忽略)
  2. 方法的三要素可以随意定义

使用steps:

  1. 接口不能直接使用,必须有一个实现类来implements 接口。
  2. 接口实现类必须覆盖重写(实现)接口中的抽象方法(除非这个实现类是抽象类)
  3. 创建实现类的对象进行使用接口

2.1 常量(接口成员变量)

syntax:
[public] [static] [final] Type NAME = value;

  1. 必须赋值
  2. 使用完全大写字母和下划线
  3. [public] [static] [final] 可省略

2.2 默认方法

在接口中新添加抽象方法,会导致别的全部实现类也要重写。但把抽象方法改为default,别的全部实现类们就不需要重写。
如果默认方法有重名,必须重新写一次。

2.3 静态方法

不能通过接口实现类的对象进行调用接口中的静态方法。
必须通过接口名称调用:接口名.静态方法名()
ps:同名不会有冲突

2.4 私有方法

只有default()可以调用
抽取common的方法,用来解决两个以上的默认方法或静态方法之间代码重复的问题。
syntax:

  1. private default RType name(){// }
  2. private static RType name(){// }

2.5 Comparable接口详解

定义
在java中接口comparable使我们经常要接触到的,比如对集合或者数组进行排序,我们经常使用到Arrays.sort()或者Collections.sort().当集合中的对象是自定义的对象时,我们有两种方法能够使排序方法应用到自定义对象的集合(数组)中。下面我们介绍Comparable的用法。

implements Comparable接口只需重写里面的compareTo(),这也是Comparable中唯一的方法
在这里插入图片描述

Steps

  1. implement Comparable<T> T为自定义类,如上Student class,如下Domino class
  2. 重写CompareTo()方法即可,以下是按从小到大的顺序排序
  3. 调用sort()

例子
1
在这里插入图片描述
2
在这里插入图片描述
3
在这里插入图片描述

2.6 Cloneable接口详解

定义
clone( )方法创建调用它的对象的一个复制副本。只有那些实现Cloneable接口的类能被复制。

注意
 Cloneable接口没有定义成员。它通常用于指明被创建的一个允许对对象进行位复制(也就是对象副本)的类。如果试图用一个不支持Cloneable接口的类调用clone( )方法,将引发一个CloneNotSupportedException异常。当一个副本被创建时,并没有调用被复制对象的构造函数。副本仅仅是原对象的一个简单精确的拷贝。

由于复制可能引起问题,因此在Object内,clone( )方法被说明为protected。这就意味着它必须或者被由实现Cloneable的类所定义的方法调用,或者必须被那些类显式重载以便它是公共的。让我们看关于下面每一种方法的例子。

steps

  1. implements cloneable()
  2. override T clone() { return (T)super.clone() }
  3. 调用clone().

1 在这里插入图片描述

2 在这里插入图片描述

3 调用 + 对比 (两个student的hashcode不同,也就是说clone方法并不是把john的引用赋予johnTheClone,而是在堆中重新开辟了一块空间,将john复制过去,将新的地址返回给johnTheClone)
在这里插入图片描述

2.7 CharSequence接口详解

现在只要有字符串就可以为CharSequence实例化,CharSequence本身是一个接口,在该接口中有如下方法(需要重写全部):
获取指定索引的字符:public char charAt​(int index);
获取字符串长度:public int length​();
截取部分字符串:public CharSequence subSequence​(int start, int end);

3. 多态 polymorphism

八、异常

1. 异常

概念:指程序执行的过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
异常是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式就是中断处理。
java.lang.Throwable 异常的根类,两个子类:java.lang.Error 和java.lang.Exception
Error:无法处理的错误,尽量避免
Exception:使用不当导致,可以纠正,有两种方法:抛出异常 或 抓住trycatch
Throwable常用方法:
void printStackTrace():打印异常的详细信息
String getMessage():获取发生异常的原因
String toString():获取异常的类型和异常描述信息(不用?)

异常查看的方法:
String getMessage()
:获取简单的异常的描述信息,原因(提示给用户时,就提示错误原因)
String toString():获取异常的类型和异常描述的详细信息
void printStackTrace():打印异常的跟踪栈信息并输出到控制台(最全面)
e.g. e.getMessage();

2. 异常分类

编译时期异常:checked异常。在编译期就会检查,如果没有处理异常,则编译失败。
运行时期异常:runtime异常。在运行时,检查异常。(编译时没有报错)

3. 异常处理

3.1 抛出异常throw

throw用在方法内,用来抛出一个异常对象,将这个异常对象传递到调用者处,并结束当前方法的执行。
syntax:
throw new 异常类名(参数)
e.g. throw newNullPointerException(“你要访问的数组不存在”);

3.2 声明异常

声明异常:将问题标识出来,报告给调用者。通过throw声明,让调用者去处理。(jvm -> 中断处理)
syntax:
modified RType name(参数)throws 异常类名1,异常类名2…{// }

注意:

  1. throws必须写在方法声明处
  2. throws后必须跟exception及其子类
  3. 方法抛多个异常,throws后面也接多个异常,若有父子关系,只写父类即可
  4. 处理声明异常
    (1) throws,交给JVM
    (2) try…catch 自己处理

4.捕获异常 try…catch

捕获异常(try-catch):javaj中对异常有针对性的语句进行捕获,可以对出现异常进行指定方式的处理。
syntax:
try{
//编写可能会出现异常的代码
}catch(异常类型 e){
//记录日志/打印异常信息/继续抛出异常
}

注意:

  1. try…catch必须一起使用。

  2. try中可能会抛出多个异常,则可以用多个catch来处理。
    (多个try 多个catch)
    (一个try 多个catch:子上父下,之类异常要求在上面的catch处理,父类的异常在下面的catch处理)
    (一个try 一个catch:catch(Exception e))

  3. 父类异常是什么,子类要么不抛异常,要么子类重写父类方法时异常就是什么。(父无子无)

  4. 有无异常皆会继续执行try…catch之后的代码,不会中断。

finally代码块

finally:在finally代码块中的代码一定会执行。
有一些特定的代码无论异常是否发生,都需要执行,但会因为异常应发的程序跳转而执行不到一些语句。把必须执行的代码放入finally代码块即可。
syntax:
try…catch…finally

注意:

  1. 只有在try或者catch中调用退出JVM的相关方法,此时finally才不会执行,否则finally一定会执行。
  2. 尽量不在finally里写return。 因为有return在finally中,会永远返回finally中的结果。

自定义异常

syntax:
public class XXXException extends Exception/RuntimeException
{
一个空参数的构造方法;
一个带异常信息的构造;
}

public class RegisterException extends Exception
{
	//一个空参数的构造方法
	public RegisterException(){
	}
	//一个带异常信息的构造
	public RegisterException(String message)
	{
		super(message)}
}

注意:

  1. 自定义异常类一般都是一Exception结尾
  2. 必须继承Exception/RuntimeException
    Exception:编译异常:throws 或 try…catch
    RuntimeException:无需处理,JVM会中断。

九、IO流

IO流分为输出流,输入流,字节流和字符流。
输出流: 把数据从其他设备上读取到内存中的流。
输入流:把数据从内存中写出到其他设备上的流。
字节流:以字节为单位,读写数据的流。(以二进制数字的形式保存)
字符流:以字符为单位,读写数据的流。(字符,可以写中文)

输入流输出流
字节流InputStreamOutputSteam
字符流ReaderWriter

1. 字节流

1.1 字节输出流OutputSteam

java.io.OutputStream 抽象类是表示字节输出流的所有超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
void close():关闭并释放资源
void flush():刷新此输出流并强制任何缓冲的输出字节被写出
void write(byte[ ] b):将b.length字节从指定的字节数组写入此输出流
void write(byte[] b, int off, int len):从指定的字节数组写入len个字节,从偏移变量off开始输出到此输出流。
abstract void write(int b):将指定的字节输出流

1.1.1 FileOutputStream类

java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件。
构造方法:
public FileOutputStream(File file):创建文件输出流以写入有指定的File对象表示的文件。
public FileOutputStream(String name):创建文件输出流以写入有指定的名称写入文件。
如果没有这个文件,会创建该文件;如果有这个文件,则会清空这个文件数据。

数据追加:
public FileOutputStream(File file,boolean append):不清空这个文件数据,而是追加数据。
public FileOutputStream(String name, boolean append)

换行:
\r\n

Steps:

  1. 创建FileOutputStream 对象,构造方法传递数据目的地
  2. 调用fos对象中的write(),把数据写入文件中
  3. 释放资源
//1. 创建FileOutputStream 对象,构造方法传递数据目的地
FileOutputStream fos = new FileOutputStream("abc.txt");
//追加:FileOutputStream fos = new FileOutputStream("abc.txt",true);

//2. 调用fos对象中的write(),把数据写入文件中
fos.write(98);

byte[] b1 = "我爱java".getBytes();
fos.write(b1);

byte[] b2 = "dasd123".getBytes();
fos.write(b2,2,5);
//3. 释放资源
fos.close();

1.2字节输入流 InputStream

java.io.IntputStream 抽象类是表示字节输入流的所有超类,可以读取字节信息到内存中。他定义了字节输入流的基本共性功能方法。
void close()
abstract int read():从输入流读取数据的下一个字节
int read(byte[ ] b):从输入流中读取一些字节数,并将他们存储到字节数组b中
读取字符:
read方法每次可以读取一个字节数据,自动转为int,读到文件结尾时返回-1。

1.2.1 FileInputStream

java.io.FileInputStream类是文件输入流,从文件中读取字节。作用:把硬盘中的数据读取到内存。
构造方法:
FileInputStream(File file):通过打开与实际文件的链接来创建一个FileInputStream,该文件有文件系统中的File对象file命名
FileInputStream(String name):通过打开与实际文件的链接来创建一个FileInputStream,该文件由文件系统中的路径名name命名。
当创建一个流对象时,必须传入一个文件路径。该路径下如果没有该文件,会抛出异常:FileNotfoundException。

NoSuchFileexception: 读的时候,找不到这个文件

Steps:

  1. 创建FileInputStream对象,构造方法绑定要读取的数据源。
  2. 使用fis.read() 读取文件(只读一个字节,自动转为int)或读byte[ ])
  3. close()
//抛异常
FileInputStream fis = new FileInputStream("abc.txt");
int len = 0;
byte[] b = new byte[1024];
while((len = fis.read(b)) != -1)
{
	sop(new String(b,0,len));
}
fis.close();
//把图片从c盘复制到d盘
FileInputStream fis = new FileInputStream("c:\\abc.txt");
int len = 0;
byte[] b = new byte[1024];
FileOutputStream fos = new FileOutputStream("d:\\abc.txt");
while(len = fis.read(b) != -1)
{
	fos.write(b, 0, len);
}
fos.close();
fis.close();

写入磁盘(fw):
在这里插入图片描述读取文件(fis和fr)
在这里插入图片描述

2. 字符流

2.1 字符输出流Writer

java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节输出流的基本共性功能方法。
void write(int c):写入单个字符
void write(char[ ] cbuf):写入字符数组
void write(String str)
vodi write(String str, int off, int len)

abstract void write(char[ ], int off, int len):写入字符数组,从off开始,写入len 个字符个数
void flush()
void close()

2.1.1 FileWriter类

java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法:
FileWriter(File file):创建一个新的FileWriter, 给定要读取的File对象
FileWriter(String fileName):创建一个新的Filewriter,给定要读取的文件名称。

FileWriter fw = new FileWriter("fw.txt");
fw.write(97);
fw.write('刷');
fw.write(3000);//中文编码表中3000对应的一个汉字
char[] chars = "java程序员".toCharArry();
fw.write(chars);
fw.write(chars, 2, 4);//vs程序
String str = "java程序员";
fw.write(str);
fw.write(str,3,2);//a程
fw.flush();
fw.close();

2.2 字符输入流Reader

java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。
字符输入流基本共性方法:
void close()
int read():从输入流读取一个字符
int read(char[ ] cbuf):从输入流读取一些字符,并将他们存储到字符数组cbuf中

2.2.1 FileReader类

java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
extends InuputStreamReader extends Reader.

构造方法:
FileReader(File file):创建一个新的FileReader,给定要读取的File对象
FileReader(String fileName):创建一个新的FileReader,给定要读取的文件名称。

读取字符:
read方法每次可以读取一个字节数据,自动转为int,读到文件结尾时返回-1。

FileReader fr = new FileReader("read.txt");
int len = 0;
char[] cbuf = new char[1024];
while((len = fr.read(cbuf)) !=-1)
{
	sou(new String(cbuf));
}
fr.close();

3. File

java.io.FIle用于文件和目录的创建,查找和删除。
构造:
File(String pathname)
File(String parents,String child)

常用方法(获取):
String getAbsolutePath()
String getPath()
long length()
static String pathSeparator()
(判断)
boolean exist()
boolean isDirectory()
boolean isFile()
(创建)
boolean createNewFile()
boolean delete()
boolean mkdir()

目录的遍历
1.String[] list()
2. File[] listFile()

4. java.io.FileFilter 接口

boolean accept(File pathname):测是否在当前File目录中。

3.缓冲流

缓冲流,也叫高效流,是对4个基本的FileXXX流的增强。
缓冲流的原理:是在创建流对象时,会创建一个内置默认大小的缓冲区数组,通过缓冲器读写,减少IO次数,从而提高读写效率。

字节缓冲流
java.io.BufferedInputStream extends InputStream
java.io.BufferedOutputStream extends OutputStream

构造:
BufferedInputStream(InputStream in):创建一个新的缓冲输入流。
BufferedOutputStream(OutputStream out)
特有方法:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("abc.txt"));
int len = 0;
byte[] b = new byte[1024];
while(len = bis.read(b) =!-1)
{
	sou(new String(b,0,len);
}
bis.close();

字符缓冲流 extends Reader/Writer
构造:
BufferedReader(Reader re)
BufferedWriter(Writer wr)
特有方法:
BufferedReader: String readLine():读一行文字
BufferedWriter:void newLine():行分隔符

BufferedWriter bw =new BufferedWriter(new FileWriter("10_io\\c.txt"));
for(int i = 0; i < 10; i++)
{
	bw.write("哦"); 
	bw.nextLine();
}
bw.flush();
bw.close();

4. 转换流

字符编码 Charset Encoding:自然语言的字符与二进制数之间的对应规则。
编码:将字符按某种规则存储到计算机中。字符 --> 字节
解码:将存储在计算机中的二进制数按照某种规则解析显示出来。字节 --> 字符
字符集/编码表Charset:生活中文字和计算机中二进制的对应规则。
常见字符集:ASCII,GBK,Unicode

ASCII:(基本)用于显示英文,字符等。

GBK:(最常用的中文码表)

Unicode:最为常用的为UTF-8,互联网工程工作小组 要求所有互联网协议都必须支持UTF-8

转换流 java.io.InputStreamReader类 是Reader的子类,是从字节流道字符流的桥梁。他读取字节并使用指定的字符集将其解码为字节。
构造:
InputStreamReader(InputStream in):创建一个使用默认字符集的字符流
InputStreamReader(InputStream in, String chasetName):创建一个使用指定字符集的字符流

//e.g. 
InputStreamReader isr = new InputStreamReader(new FileInputStream("t.txt"), "GBK")
int len = 0;
while(len = isr.read() !=-1)
{
	sop((char)read)}

转换流 java.io.OutputStreamWriter类 是Writer的子类,是从字符流道字节流的桥梁。他读取字节并使用指定的字符集将其解码为字节。
构造:
OutputStreamWriter(OutputStream out):创建一个使用默认字符集的字符流
OutputStreamWriter(OutputStream out, String chasetName):创建一个使用指定字符集的字符流

十、序列化 流?

概念:序列化机制用一个字节序列可以表示一个对象,该字节序列包含该对象的数据、对象的类型和对象中存储的属性等信息。字节序列写出到文件之后,相当于文件中持久保存了一个对象的信息。
反之,反序列化即把文件中保存的对象,使用流的方式读出来,叫做读对象。
序列化:
java.io.ObjectOutputStream类 将java对象的原始数据类型写出到文件,实现对象的持久储存。
构造:
ObjectOutputStream(OutputStream out)

序列化操作:

  1. 必须实现java.io.Serializable接口
  2. 该类所有属性必须是可系列化的,若有一个属性不需要可序列化的,则该属性需要注明是瞬态的–使用transient关键字修饰(静态不可)

反序列化:
ObjectInputStream,将之前使用的序列化的原始数据恢复为对象。
构造:
ObjectInputStream(InputStream in)
方法:
public final Object readObject():读取一个对象。

Steps:

Employee e = null;

ObjectInputStream in = new ObjectInputStream(new FileInputStream("Employee.txt"));
e = (Employee)in.readObject();
in.close();
fileIn.close();

注意:

  1. static不可被序列化
  2. transient 瞬态关键字 不可被序列化。
  3. 对于JVM可以反序列化对象,它必须是能够找到class文件的类。如果找不到该类的class文件,则抛出一个classNotFoundException异常。
  4. 找得到class文件,但是class文件在序列化对象后发生了修改,那么反序列化操作也会失败。
    解决: 手动给无法改变的序列号
    e.g. private static final long serialVersionUID = 1L;

十一、反射 ?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象。

反射是框架设计的灵魂
(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

反射本质:获取class对象之后,反向获取student/xx 对象的各中信息

以上反射内容retrieved from https://blog.csdn.net/qq_36226453/article/details/82790375

十二、动态代理 ???

JAVA的动态代理
代理模式
代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。
优点一:可以隐藏委托类(工厂)的实现;-----(关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者”对我们来说是不可见的)
优点二:可以实现客户与委托类间的解耦,在不修改委托类代码的情况下能够做一些额外的处理。

按照代理的创建时期,代理类可以分为两种。

静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

动态代理
代理类在程序运行时创建的代理方式被成为 动态代理。 也就是说,这种情况下,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的“指示”动态生成的。相比于静态代理, 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值