Java 基础

Posted 说到做到_我的忍道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 基础相关的知识,希望对你有一定的参考价值。

一、数据类型

1. 包装类型

boolean/1 

byte/8

char/16

short/16

int/32

float/32

long/64

double/64

装箱与拆箱

Integer x =2 // 装箱

int y =2;//拆箱

2. 缓存池

new Integer(123)与Integer.valueOf(123)的区别在于:

new Integer(123)每次都会创建一个对象

Integer.valueOf(123)会使用缓存池中的对象,多次调用会取得同一个对象的引用。

        
        Integer x = new Integer(123);
        Integer y = new Integer(123);
        System.out.println( x==y );
        Integer m = Integer.valueOf(123);
        Integer k = Integer.valueOf(123);
        System.out.println( m == k);

编译器会在自动装箱过程中调用valueOf()方法, 因此多个Integer实例使用自动装箱来创建并且值相同,那么就会引用相同的对象。 

基本类型对应的缓冲池如下:

boolean : true false

all byte values

short/int values between -128 and 127

char in the range \\u0000 to \\u007F

在使用这些基本类型对应的包装类型时,就可以直接使用缓冲池的对象。

二、String

概览

String 被声明为final, 因此它不可被继承。

value 数组被声明为final, 这意味着value数组初始化之后就不能再引用其他数组。并且String内部没有改变value数组的方法,因此可以保证String不可变。

不可变的好处

1. 可以缓存hash值

因为String的hash值经常被使用,例如String用做HashMap的key。不可变的特性可以使得hash值也不可变,因此只需要进行一次计算。

2. String Pool 的需要

如果一个String对象已经被创建过了,那么就会从String Pool中取得引用。只有String是不可变的,才可能使用String Pool。

3. 安全性

String经常作为参数,String不可变性可以保证参数不可变。例如再作为网络连接参数的情况下如果String是可变的,那么再网络连接过程中,String被改变,改变String对象的那一方以为现在连接的是其他主机,而实际情况不一定是。

4. 线程安全

String 不可变性天生具备线程安全,可以在多个线程中安全地使用。

String, StringBuffer and StringBuilder

1. 可变性

String不可变

StringBuffer和StringBuilder可变

2. 线程安全

String不可变,所以线程安全

StringBuilder不是线程安全的

StringBuffer是线程安全的,内部使用synchronized进行同步

String Pool

字符串常量池(String Pool)保存着所有字符串字面量, 这些字面量在编译时期就确定。不仅如此,还可以使用String的intern()方法在运行过程中讲字符串添加到String Pool中。

当一个字符串调用intern()方法时,如果String Pool中已经存在一个字符串和该字符串值相等(使用equals()方法进行确定),那么就会返回String Pool中字符串的引用;否则,就会在String Pool中添加一个新的字符串,并返回这个新字符串的引用。

new String("abc")

使用这种方式一共会创建两个字符串对象(前提是String Pool中还没有“abc”字符串对象)。

“abc”属于字符串字面量,因此编译时期会在String Pool中创建一个字符串对象,指向这个“abc”字符串字面量;

而使用new的方式会在堆中创建一个字符串对象。

三、运算

参数传递

Java的参数是以值传递的形式传入方法中,而不是引用传递。

float 与 double

Java不能隐式执行向下转型,因为这会使得精度降低。

1.1 字面量属于double类型,不能直接将1.1直接赋值给float变量,因为这是向下转型。

1.1f 字面量才是float类型

隐式类型转换

因为字面量1是int类型,他比short类型精度要高,因此不能隐式地将int类型转型为short类型。

但是使用 += 或者 ++ 运算符可以执行隐式类型转换。

switch语句可以使用String对象。

四、继承

访问权限

private、protected和public,如果不加修饰符,表示包级可见。

可以对类或类中的成员加上修饰符。

类可见表示其他类可以使用这个类创建实例对象。

成员可见表示其他类可以用这个类的实例对象访问到该成员。

protected用于修饰成员,表示在继承体系中成员对于子类可见,但是这个访问修饰符对于类没有意义。

设计良好的模块会隐藏所有的实现细节,把他的API与他的实现清晰地隔离开来。模块之间只通过他们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念被称为信息隐藏或封装。因此访问权限应当尽可能地使每个类或者成员不被外界访问。

如果子类的方法重写了父类的方法,那么子类中该方法的访问级别不允许低于父类的访问级别。这是为了确保可以使用父类实例的地方都可以使用子类实例,也就是确保满足里式替换原则。

字段绝不能是公有的,因为这么做的话就失去了对这个字段修改行为的控制,客户端可以对其随意修改。

抽象类与接口

1. 抽象类

抽象类和方法都用abstract关键字。抽象类包含抽象方法,抽象方法包含于抽象类中。

抽象类和普通类最大的区别就是,抽象类不能被实例化,需要继承才能实例化其子类。

2. 接口

可以有默认的方法实现,

接口的成员(字段和方法)默认都是public的,并且不允许定义为private或者protected。

接口的字段默认都是static和final的。

3. 比较

从设计层面上看,抽象类提供了一种IS-A关系,那么就必须满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种LIKE-A关系,他只是提供一种方法实现契约,并不要求接口和实现接口的类具有IS-A关系。

从使用上来看,一个类可以实现多个接口,但是只能继承一个抽象类。

接口的字段只能是static和final的,而抽象类的字段没有这种限制。

接口的成员只能是public的,而抽象类的成员可以有多种访问权限。

4. 使用选择

使用接口:

需要让不相关的类都实现一个方法,例如不相关的类都可以实现Compareable接口中的compareTo()方法;

需要使用多重继承

使用抽象类:

需要在几个相关的类中共享代码

需要能控制继承来的成员的访问权限,而不是都为public

需要继承非静态和非常量字段

在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活的为一个类添加行为。并且从Java8开始,接口也可以有默认的方法实现,使得修改接口的成本变得很低。

super

访问父类的构造函数:可以使用super()访问父类的构造函数

访问父类的成员:super引用父类方法

重写与重载

重写(Overload)

存在于继承体系中,指子类实现了一个于父类在方法声明上完全相同的一个方法

满足里式替换原则:

1. 子类访问权限必须大于等于父类方法

2. 子类方法的返回类型必须是父类方法返回类型或其子类

使用@Override, 可以让编译器帮助检查是否满足

重载(Overload)

存在于同一个类中,指一个方法与已经存在的方法名称一样,但是参数类型、个数、顺序至少一个不同

注意:只有返回值不同不算重载

五、Object通用方法

equals()

对于基本类型, == 判断两个值是否相等,基本类型没有equals()方法

对于引用类型, == 判断两个变量是否引用同一个对象,而equals()判断引用的对象是否等价

hashCode()

hashCode() 返回散列值,而equals()是用来判断两个对象是否等价。等价的两个对象散列值一定相同,但是散列值相同的两个对象不一定等价。

在覆盖equals()方法时应当总是覆盖hashCode()方法,保证等价的两个对象散列值也相等。

toString()

默认返回xxx@4554716c这种形式,其中@后面的数值为散列码的无符号十六进制表示。

clone()

1. cloneable

clone() 是 Object的protected方法,它不是public, 一个类不显式去重写clone(),其他类就不能直接去调用该类实例的clone()方法。

clone() 方法并不是Cloneable接口的方法,而是Object的一个protected方法。Cloneable接口只是规定,如果一个类没有实现Cloneable接口又调用了clone()方法,就会抛出CloneNotSupportedException。

2. 浅拷贝

拷贝对象和原始对象的引用类型引用同一个对象。

3. 深拷贝

拷贝对象和原始对象的引用类型引用不同对象。

4. clone的替代方案

可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象

六、关键字

final

1. 数据

声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量。

对于基本类型,final使数值不变

对于引用类型,final使引用不变,也就不能引用其他对象,但是被引用的对象本身是可以修改的。

2. 方法

声明方法不能被子类重写。

private方法隐式地被指定为final,如果在子类中定义的方法和基类中的一个private方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。

3. 类

声明类不允许被继承。

static

1. 静态变量

静态变量:类变量,属于类,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。

实例变量:每创建一个实例就会产生一个实例变量,它与该实例同生共死。

2. 静态方法

静态方法:静态方法在类加载的时候就存在了,它不依赖于任何实例。所以静态方法必须有实现,不能是抽象方法。

只能访问所属类的静态字段和静态方法,方法中不能有this和super关键字。

3. 静态语句块

在类初始化时运行一次。

4. 静态内部类

非静态内部类依赖于外部类的实例,而静态内部类不需要。

静态内部类不能访问外部类的非静态的变量和方法。

5. 静态导包

使用静态变量和方法时不需要指明ClassName,从而简化代码,但是可读性大大降低。

6. 初始化顺序

静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于他们在代码中的顺序。

七、 反射

每个类都有一个Class对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着Class对象。

类加载相当于Class对象的加载,类在第一次使用时才动态加载到JVM中,也可以使用 Class.forName("com.mysql.jdbc.Driver") 这种方式来控制类的加载, 该方法会返回一个Class对象。

反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的.class 不存在也可以加载进来。

八、 异常

Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: Error 和 Exception。其中 Error 用来表示 JVM 无法处理的错误,Exception 分为两种:

  • 受检异常 :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复;
  • 非受检异常 :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序崩溃并且无法恢复。

 

九、泛型

public class Box<T> 
    // T stands for "Type"
    private T t;
    public void set(T t)  this.t = t; 
    public T get()  return t; 

十、注解

Java 注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。注解不会也不能影响代码的实际逻辑,仅仅起到辅助性的作用。 

 

Java 与 C++ 的区别

  • Java 是纯粹的面向对象语言,所有的对象都继承自 java.lang.Object,C++ 为了兼容 C 即支持面向对象也支持面向过程。
  • Java 通过虚拟机从而实现跨平台特性,但是 C++ 依赖于特定的平台。
  • Java 没有指针,它的引用可以理解为安全指针,而 C++ 具有和 C 一样的指针。
  • Java 支持自动垃圾回收,而 C++ 需要手动回收。
  • Java 不支持多重继承,只能通过实现多个接口来达到相同目的,而 C++ 支持多重继承。
  • Java 不支持操作符重载,虽然可以对两个 String 对象执行加法运算,但是这是语言内置支持的操作,不属于操作符重载,而 C++ 可以。
  • Java 的 goto 是保留字,但是不可用,C++ 可以使用 goto。
  • Java 不支持条件编译,C++ 通过 #ifdef #ifndef 等预处理命令从而实现条件编译。

 

以上是关于Java 基础的主要内容,如果未能解决你的问题,请参考以下文章

Java基础:String不可变性和final修饰

JAVA基础补漏--可变参数

java 基础

JAVA核心技术I---JAVA基础知识(不可变对象和字符串)

Java基础16----方法可变参数

Java基础16----方法可变参数