目录
1.String、StringBufer、StringBuilder
1.1 String
1.2 StringBuffer、StringBuilder
1.3 Efficiency
2. Interface and abstract class
3. 运算符
3.1. 移位运算符
4. IO 输入输出流
(1)IO流的分类
(2)字节流和字符流
4.1 输出字节流 OutputStream
4.1.1 FileOutputStream
(1) 构造方法
(2) FileOutputStream的写入方法
(3) Demo
4.2 输入字节流 InputStream
4.2.1 FileInputStream
(1) demo
框架学再多,基础甚至底层都不会有什么用哟。面试的时候就只能说我会用框架,一问理论、底层就懵逼了。原来我只是会用,仅仅会用。自学了那么多框架,结果面试都过不了。多么嘲讽的。大学刚毕业的那时候,没有人告诉你需要做什么?虽然之前在某公司IT部独立负责三个项目的二次开发,依旧没能遇到引路人。就这样当条咸鱼,偶尔学学框架敲敲代码,甚至连BAT也没有想过。没有一点点的挣扎就随便选了一家公司然后开始了。
现在想来甚是后悔,就应该在大一的时候开始想要做什么?要学什么?要去哪里?然后开始准备了。
那就从现在开始,开始复习开始刷题吧!希望一年后能遇到更好的自己。
String是只读字符串,典型的Immutable对象,对它的任何改动。起手都是创建一个新对象,再把引用指向该对象。String对象赋值操作后,会在常量池中进行缓存。如果下次引用的时候,该对象已经存在就会直接调用缓存池中。StringBuffer则是可以在原对象上进行修改,是线程安全的。StringBuffer和StringBuilder都是继承了AbstractStringBuilder。该抽象类也是以字符数组的形式存储字符串。StringBuilder线程不安全,但是效率比StringBuffer高。
String对象是不可变,也是不可继承的。如下源码中String是被final所修饰的。
public final class String
implements java.io.Serializable, Comparable
private final char value[];
/** Omit resource code …… . */
}
String 为不可变对象,一旦被创建,就不能修改它的值. . 对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.
String中的对象是不可变的,也就可以理解为常量, 显然线程安全 。
StringBuffer、StringBuilder都是继承AbstractStringBuilder类。
在AbStaractStringBuiler中使用字符数组保存字符串。可知这两种对象都是可变的。
abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value;
/** Omit resource code …… . */
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
/** --------StringBuffer Resource code-------------- */
public StringBuffer(int capacity) {
super(capacity);
}
public StringBuffer() {
super(16);
}
StringBuffer:是一个可变对象,当对他进行修改的时候不会像String那样重新建立对象 , 它只能通过构造函数来建立, 如: StringBuffer sb = new StringBuffer();
不能通过赋值符号对他进行付值. , 如 sb = "welcome to here!";//error
对象被建立以后,在内存中就会分配内存空间,并初始保存一个null.向StringBuffer中赋值的时候可以通过它的append方法. sb.append("hello");
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
/** --------StringBuffer Resource code-------------- */
@Override
public synchronized int length() {
return count;
}
@Override
public synchronized int capacity() {
return value.length;
}
@Override
public synchronized void ensureCapacity(int minimumCapacity) {
super.ensureCapacity(minimumCapacity);
}
/** --------Omit Resource code-------------- */
StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。
效率比较String < StringBuffer < StringBuilder,但是在String S1 =“This is only a”+“simple”+“test”时,String效率最高。
参考CSDN文档:https://blog.csdn.net/aptentity/article/details/68942916
参考CSDN文档:https://blog.csdn.net/Speed_Pig/article/details/71628368?locationNum=3&fps=1(1.8特性)
类型 | abstract class | interface |
定义 | abstract class 关键词 | Interface关键字 |
继承 | 抽象类可以继承一个类或者实现多个接口。子类只能实现一个抽象类 | 接口类只可以继承接口(一个或者多个)。子类可以实现多个接口 |
访问修饰符 | 抽象方法可以有public、protected和default这些修饰符 JDK1.8以前 抽象类的方法默认访问权限为protected,JDK1.8后,默认访问权限变为default. |
接口方法默认修饰符是public abstract。你不可以使用其它修饰符。1.8版本允许定义static 、default 接口中的变量隐式声明为public static final |
方法实现 | 可以定义构造方法,抽象方法,具体方法 | 接口完全抽象,没有方法体。1.8后允许在接口里面定义default,static方法体 |
实现方式 | 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的抽象方法的实现,可以选择所需的非抽象方法的实现。通过super去调用抽象类中的方法参数。 | 子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现 |
作用 | 把相同的东西提取出来,即重用 | 为了把程序模块进行固化的契约,是为了降低偶合 |
int i = 4<<3 ;
//4<<1 -> 4 X 2^1 8
//4<<2 -> 4 X 2^2 16
//4<<3 -> 4 X 2^3 32
//4<<4 -> 4 X 2^4 64
System.out.println(i);
i = 64>> 3;
//64>>1 64/2 32
//64>>2 64/(2^2) 16
//64>>3 64/(2^3) 8
//64>>4 64/(2^4) 4
System.out.println(i);
在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream。
在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。
字节流 传输的是字节,字符流传输的是字符,一般图片、音频等是通过字节流,文本是通过字符流。
处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。
public abstract class OutputStream implements Closeable, Flushable
输出流FileOutputStream把数据写入本地文件。
文件字节输出流写入文件内容的步骤:
* 1.选择流:创建流对象
* 2.准备数据源,把数据源转换成字节数组类型
* 3.通过流向文件当中写入数据
* 4.刷新流
* 5.关闭流
getChannel() 方法返回与此文件输出流关联的唯一文件通道对象。
getSecurityManager : 当运行未知的Java程序的时候,该程序可能有恶意代码(删除系统文件、重启系统等),为了防止运行恶意代码对系统产生影响,需要对运行的代码的权限进行控制,这时候就要启用Java安全管理器。
Native : 调用非java代码的接口 。
/**
*name : 一般为路径地址
*append: append参数为true时,数据从文件尾部写入;append参数为false时,数据覆盖原文件。
*FileNotFoundException :文件未找到
*/
public FileOutputStream(File file) throws FileNotFoundException {
this(file, false);
}
// 不使用File对象,直接传入文件路径。
public FileOutputStream(String name) throws FileNotFoundException {
//new File(name) 则创建 file对象
this(name != null ? new File(name) : null, false);
}
//不使用File对象 打开文件,设置插入方式。
public FileOutputStream(String name, boolean append)
throws FileNotFoundException
{ //调用该类2参数构造方法
this(name != null ? new File(name) : null, append);
}
//使用File对象,设置插入方式
public FileOutputStream(File file, boolean append)
throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
/*getSecurityManager安全管理*/
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkWrite(name);
}
if (name == null) {
throw new NullPointerException();
}
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
this.fd = new FileDescriptor();
fd.attach(this);
this.append = append;
this.path = name;
open(name, append); // 打开文件
}
public FileOutputStream(FileDescriptor fdObj) {
SecurityManager security = System.getSecurityManager();
if (fdObj == null) {
throw new NullPointerException();
}
if (security != null) {
security.checkWrite(fdObj);
}
this.fd = fdObj;
this.append = false;
this.path = null;
fd.attach(this);
}
/* 打开文件,为了下一步写入文件内容以及位置。native方法 */
private native void open0(String name, boolean append)
throws FileNotFoundException;
private void open(String name, boolean append)
throws FileNotFoundException {
open0(name, append);
}
write(byte b[], int off, int len) 从off开始到len不包含len。
append :写入起始处模式
private native void write(int b, boolean append) throws IOException;
/* 将指定的字节b写入到该文件输入流 */
public void write(int b) throws IOException {
write(b, append);
}
/* 将指定的字节数组写入该文件输入流,并指定文件写入起始处模式 */
private native void writeBytes(byte b[], int off, int len, boolean append)
throws IOException;
/* 将指定的字节数组b写入该文件输入流 */
public void write(byte b[]) throws IOException {
writeBytes(b, 0, b.length, append);
}
/* 将指定len长度的字节数组b写入该文件输入流 */
public void write(byte b[], int off, int len) throws IOException {
writeBytes(b, off, len, append);
}
@Test
public void StringDemo() {
File file = new File("d://s.txt");
try {
FileOutputStream fileOutputStream = new FileOutputStream(file,true);
String str = "exlx";
for (int i = 0 ; i< str.length();i++){
//转化成int 写入
int b = (int)str.charAt(i);
fileOutputStream.write(b);
}
//2、把string转换为byte数组;
byte[] array = str.getBytes() ;
//3、把byte数组输出;
fileOutputStream.write( array,0,1); //存储 e
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
文件字节输入流读取文件内容的步骤:
* 1.创建流对象
* 2.创建一个缓存字节的容器数组
* 3.定义一个变量,保存实际读取的字节数
* 4.循环读取数据
* 5.操作保存数据的数组
* 6.关闭流
int size = in.available();返回可以不受阻塞地从此文件输入流中读取的字节数。
注意:获取网络数据可能存在延迟导致字节数错误。获取网络:https://blog.csdn.net/zyxwvuuvwxyz/article/details/78549923
public synchronized void mark(int readlimit) 标记当前位置,此输入流在标记位置无效之前允许读取的字节数。
注意: 如果读取字节 < readlimit 可以通过调用rest()将流指标复位到标记处。如果readlimit参数比较大,底层buf也会自动扩大其size以支持更大readlimit参数.
@Test
public void demo(){
try {
InputStream in = new URL("http://www.apache.org").openStream();
//2. 返回这个输入流中可以被读的剩下的bytes字节的估计值;
int size = in.available() ;
//3. 根据输入流中的字节数创建byte数组;
byte[] array = new byte[size];
//4.把数据读取到数组中;
in.read( array ) ;
//5.根据获取到的Byte数组新建一个字符串,然后输出;
String result = new String(array);
System.out.println(in.available());
FileOutputStream outputStream = new FileOutputStream("d://s.txt");
outputStream.write(array);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
JavaIO流详解: https://blog.csdn.net/zhaoyanjun6/article/details/54292148/
Java IO流学习总结一:输入输出流 https://blog.csdn.net/zhaoyanjun6/article/details/54292148/