Java 基础知识总结-2

0. 数据类型

这里写图片描述

1. String 是引用类型,底层用 char 数组实现的.

2. short s1 = 1; s1 = s1 + 1; 有错吗?short s1 = 1; s1 += 1 有错吗;

  • 前者不正确,后者正确。
  • 对于 short s1 = 1; s1 = s1 + 1;由于 1 是 int 类型,因此 s1+1 运算结果也是 int 型,
    需要强制转换类型才能赋值给 short 型.
  • 而 short s1 = 1; s1 += 1;可以正确编译,因为 s1+= 1;相当于 s1 =(short)(s1 + 1);其中有隐含的强制类型转换。

3. int与Integer的基本使用对比

  • Integer是int的包装类;int是java的一种基本数据类型 。Integer变量须实例化后才能使用;int变量不需要
  • Integer实际是对象的引用,当new一个Integer时,实际是生成一个指针指向此对象;int则直接存储数据值
  • Integer的默认值是null;int的默认值是0

int与Integer的深入对比

  1. 由于Integer实际是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。

    Integer i = new Integer(100);
    Integer j = new Integer(100);
    System.out.print(i == j); //false
  2. Integer变量和int变量比较时,只要两个变量的值是相等的,则结果为true(因包装类Integer和基本数据类型int比较时,会自动拆包装为int进行比较,就变为两个int变量的比较)

    Integer i = new Integer(100);
    int j = 100;
    System.out.print(i == j); //true
  3. 非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)

    Integer i = new Integer(100);
    Integer j = 100;
    System.out.print(i == j); //false
  4. 对于两个非new生成的Integer对象,比较时如两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true
Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false
```      




<div class="se-preview-section-delimiter"></div>

###### 第4条原因: 编译Integer i=100时,会翻译成为Integer i=Integer.valueOf(100)。而API中对Integer类型的valueOf的定义:对于-128127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了。





<div class="se-preview-section-delimiter"></div>

public static Integer valueOf(int i){
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high){
return IntegerCache.cache[i + (-IntegerCache.low)];
}
return new Integer(i);
}






<div class="se-preview-section-delimiter"></div>

#4. 数据类型之间的转换
1. 字符串如何转基本数据类型?
 调用基本数据类型对应的包装类中的方法 parseXXX(String)或 valueOf(String)即可返回相应基本类型。
2. 基本数据类型如何转字符串?
- 一种方法是将基本数据类型与空字符串(“”)连接(+)即可获得其所对应的字符串;
- 另一种方法是调用 String类中的 valueOf()方法返回相应字符串。





<div class="se-preview-section-delimiter"></div>

#5. Java 中有几种类型的流
* 按照流的方向:输入流(inputStream)和输出流(outputStream)。
* 按照实现功能分:节点流(可从或向一特定地方(节点)读写数据。如 FileReader)和处理流(对一个已存在的流连接和封装,通过所封装流的功能调用实现数据读写。如 BufferedReader。处理流的构造方法总要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。)
* 按照处理数据的单位:字节流和字符流。字节流继承于 InputStream 和 OutputStream,字符流继承于InputStreamReader 和 OutputStreamWriter。

![这里写图片描述](https://img-blog.csdn.net/20180424121919964?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpeWlmYW42ODc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)




<div class="se-preview-section-delimiter"></div>

##5.2.  字节流如何转为字符流
* 字节输入流转字符输入流通过 InputStreamReader 实现,该类的构造函数可以传入 InputStream 对象。
* 字节输出流转字符输出流通过 OutputStreamWriter 实现,该类的构造函数可以传入 OutputStream 对象。




<div class="se-preview-section-delimiter"></div>

##5.3.  字节流和字符流的区别
* 字节流读取的时候,读到一个字节就返回一个字节;字符流使用了字节流读到一个或多个字节(中文对应的字节数是两个,在 UTF-8 码表中是 3 个字节)时。先去查指定的编码表,将查到的字符返回。 
* 字节流可以处理所有类型数据,如:图片,MP3,AVI 文件,而字符流只能处理字符数据。
* 只要是处理纯文本数据,就要优先考虑使用字符流,除此之外都用字节流。
* 字节流主要是操作 byte 类型数据,以 byte 数组为准,主要操作类就是 OutputStream、InputStream;字符流处理的单元为 2 个字节的 Unicode 字符,分别操作字符、字符数组或字符串
* 字节流处理单元为 1 个字节,操作字节和字节数组。所以字符流是由 Java 虚拟机将字节转化为 2 个字节的 Unicode 字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流好点。在程序中一个字符等于两个字节,java 提供了 Reader、Writer 两个专门操作字符流的类。




<div class="se-preview-section-delimiter"></div>

#6. java对象复制
![这里写图片描述](https://img-blog.csdn.net/20180424121938636?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpeWlmYW42ODc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)





<div class="se-preview-section-delimiter"></div>

###深克隆

     在浅度克隆的基础上,对于要克隆的对象中的非基本数据类型的属性对应的类,也实现克隆,这样对于非基本数据类型的属性,复制的不是一份引用,即新产生的对象和原始对象中的非基本数据类型的属性指向的不是同一个对象

      深度克隆步骤:
      要克隆的类和类中所有非基本数据类型的属性对应的类
        1、都实现java.lang.Cloneable接口
        2、都重写java.lang.Object.clone()方法

Java代码实例:




<div class="se-preview-section-delimiter"></div>

```public class Attribute implements Cloneable {   
    private String no;      
    public Object clone() {   
        try {   
            return super.clone();   
        } catch (CloneNotSupportedException e) {   
            return null;   
        }   
    }   
}   

public class Product implements Cloneable {
private String name;
private Attribute attribute;
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
}
}

7. 序列化

  Java序列化是指把Java对象保存为二进制字节码的过程,Java反序列化是指把二进制码重新转换成Java对象的过程。

那么为什么需要序列化呢?

  • 第一种情况:一般Java对象的声明周期比Java虚拟机的要短,实际中希望在JVM停止运行之后能够持久化指定的对象,这时就需把对象进行序列化之后保存。

  • 第二种情况:需把Java对象通过网络进行传输时。因数据只能够以二进制的形式在网络中传输,当把对象通过网络发送出去前需先序列化成二进制数据,在接收端读到二进制数据之后反序列化成Java对象。

    1. 在Java中,只要一个类实现了java.io.Serializable接口,那么它就可以被序列化。

    2. 通过ObjectOutputStream和ObjectInputStream对对象进行序列化及反序列化

    3. 虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID)

    4. 序列化并不保存静态变量。

    5. 要想将父类对象也序列化,就需要让父类也实现Serializable 接口。

    6. Transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。

    7. 服务器端给客户端发送序列化对象数据,对象中有一些数据是敏感的,比如密码字符串等,希望对该密码字段在序列化时,进行加密,而客户端如果拥有解密的密钥,只有在客户端进行反序列化时,才可以对密码进行读取,这样可以一定程度保证序列化对象的数据安全。

8. Java 内部类

  1. 静态嵌套类 (Static Nested Class) 和内部类(Inner Class)的不同?
    • 静态嵌套类:Static Nested Class 是被声明为静态(static)的内部类,它可以不依赖于外部类实例被实例化。
    • 内部类:需要在外部类实例化后才能实例化,其语法看起来挺诡异的。

猜你喜欢

转载自blog.csdn.net/liyifan687/article/details/80062974