面向对象与java
面向对象的三种基本特征:继承、封装、多态。
- 封装:将对象的实现细节隐藏起来,通过一些公用方法来暴露该对象的功能。
- 继承:面向对象实现软件复用的重要手段。
- 多态:子类对象可以直接赋给父类变量,但运行时依然表现出子类的行为特征,这意味着同一个类型的对象在执行同一个方法时,可能表现出多种行为特征。
当程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为它从父类继承得到的所有实例变量分配内存。
类是具有共同属性、共同方法的一类事物。类是对象的抽象;对象则是类的实例。
java不允许直接访问对象,而是通过对对象的引用来操作对象。
- 引用变量(指针)里存放的仅仅是一个引用(地址值),它指向实际的对象。堆内存里的对象可以有多个引用,即多个引用变量指向同一个对象。
this
总是指向调用该方法的对象。最大的作用就是让类中一个方法,访问该类里的另一个方法或实例变量。- java把内存划分为两种:
栈内存
和堆内存
。栈内存当超过变量的作用域后,java会自动释放为该变量分配的内存空间;堆内存用来存放由new创建的对象和数组,在堆中分配的内存,由java虚拟机的自动垃圾回收器来管理。
数据类型
java 是强类型语言,强类型包含两方面的含义:
- 所有的变量必须先声明、后使用
- 指定类型的变量只能接受类型与之匹配的值
java数据类型分为两类:基本类型和引用类型。
8中基本数据类型
- byte:1个字节(-128 ~ 127)
- short:2个字节
- int:4个字节
- long:8个字节
- float:4个字节
- double:8个字节
- char:2个字节
- boolean:1个字节
引用数据类型
类、接口、数组
java中整数值有4种表示方式:十进制、二进制(0B)、八进制(0)、十六进制(0X)
原码:最高位为符号位,0代表正数,1代表负数。
反码:正数的反码是原码;负数的反码在原码基础上,符号位不变,其他位取反。
补码:正数的补码是原码;负数的补码是其反码加1。
为了解决原码做减法的问题,出现了反码;为了解决-0,出现了补码。**计算机是以补码的形式保存所有的整数。**8位二进制,原码与反码表示范围是[-127,127],而使用补码表示范围是[-128,127]
java语言所提供的7种数值类型之间可以相互转换,两种转换方式:自动类型转换
和强制类型转换
。
// 强制类型转换语法格式。大转小
(targetType)value
运算符
- 算术运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 位运算符:&、|、~(按位非)、^(按位异或)、<<(左移运算符)、>>(右移运算符)、>>>(无符号右移运算符)
- 类型相关运算符
>>
:右移运算符,右移n位相当于除以2的n次方
<<
:左移运算符,左移n位相当于乘以2的n次方
>>>
:无符号右移
例:2乘以8最有效率的方法是,2<<3;因为位运算是CPU直接支持的,效率最高。
流程控制
- 分支结构:if和switch
- 循环结构:while、do while、for、foreach(JDK 5支持)
foreach:
for (type variableName : array | collection) {
// variableName 自动迭代访问每个元素…
}
switch支持byte、short、char、int、枚举类型、String(Java 7支持)
do {//至少执行一次
} while();
break不仅结束其所在的循环,还可以直接结束其外层循环。
跳出多重循环时,可以使外层的循环条件表达式的结果受到里层循环体代码的控制。
数组
数组的初始化完成,在内存中所占的空间将被固定下来,因此数组长度不可改变。
- 静态初始化:arrayName = new type[]{element1,element2…}
- 动态初始化:arrayName = new type[length]
数组是一种引用数据类型,数组引用变量只是一个引用,数组元素和数组变量在内存里是分开存放的。实际的数组对象存储在堆(Heap)内存中;如果引用该数组对象的数组引用变量是局部变量,存储在栈(Stack)内存中。
每个方法执行时,建立自己的内存栈,方法内部定义的变量将会逐个放入这块栈内存里,方法结束,内存栈自然销毁;在程序中创建一个对象时,这个对象被保存到运行时数据区,方便反复利用,这个运行时数据区就是堆内存。
关键字
static
- static修饰的成员不能访问没有static修饰的成员。
- static修饰的成员表明它属于这个类本身,而不属于该类的单个实例。
final
final修饰变量称为常量。常量命名规范,字母大写,单词间用下划线分开。如public static final KEY_MAN;
- final 成员变量可以指定默认值,也可以在构造器或初始化块中分配初始值。
- final修饰的形参不能赋值
- final 引用类型变量,引用地址不变,但对象属性可以发生改变。
- final 方法不可被重写,Object类getClass();可以被重载。
- final 类不可以有子类
default
java 8 中新增的关键字。
transient
抽象类与接口
抽象(abstract)
- 抽象类里可以没有抽象方法。抽象方法不能有方法体。
- 抽象类
不能被实例化
。抽象类的构造器不能用于创建实例,主要用于被其子类调用。 - final 和 abstract 永远不能同时使用。(abstract修饰类只能被继承,修饰方法必须由子类重写;fina修饰类不能被继承,修饰方法不能被重写)
- abstract 不能用于修饰成员变量和局部变量;不能修饰构造方法。
- static 和 abstract 不能同时修饰某个方法,但可以同时修饰内部类。abstract 修饰方法不能定义为private 访问权限。
抽象类体现的是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造。
接口(interface)
接口里不能包含普通方法,接口里的所有方法都是抽象方法。Java 8 对接口进行了改进,允许在接口中定义默认方法,默认方法可以提供方法实现。
一个接口可以有多个直接父接口,但接口只能继承接口,不能继承类。
接口里可以包含成员变量(只能是静态常量)、方法(只能是抽象实例方法、类方法或默认方法)、内部类(包括内部接口、枚举)
接口中定义成员变量时,不管是否使用 public static final 修饰符,接口里的成员变量总是使用这三个修饰符来修饰;
// java 8 允许在接口中定义类方法、默认方法
public interface Test {
static void method() {
System.out.println("接口中定义静态方法");
}
default void test() {
System.out.println("默认方法");
}
void empty();
}
内部类
内部类主要用于设计具有相互协作关系的类集合。
内部类比外部类可以多使用三个修饰符:private、protected、static
非静态内部类
静态内部类
static 修饰一个内部类时,则这个内部类就属于外部类本身,而不属于外部类的某个对象。
局部内部类
在方法内部定义一个内部类时,称为局部内部类。
匿名内部类
匿名内部类适合创建只需要一次使用的类。
- 匿名内部类
不能是抽象类
。系统创建匿名内部类时,会立即创建匿名内部类的对象。 - 匿名内部类
不能定义构造器
。匿名内部类没有类名,所以无法定义构造方法,可以定义初始化块。
枚举类
java 5 开始支持枚举(关键字 enum
)。添加了抽象类 java.lang.Enum
,在枚举中可以定义属性、构造方法、普通方法、抽象方法。
可以像使用普通的类一样使用枚举,编译器做了些什么?欲知详情,最有效的途径就是查看生成的字节码。
枚举类与普通类的区别?
- 枚举类默认继承了 java.lang.Enum 类,而不是默认继承 Object 类
- 枚举类不能派生子类。默认使用 final 修饰
- 枚举类的所有实例必须在枚举类的第一行显式列出,否则这个枚举类永远都不能产生实例。
泛型
Java SE 5新增泛型(实现了参数化类型的概念)概念。编写可以应用于各种类型的代码。
类型参数,用尖括号括住,放在类名后面。然后在使用这个类的时候,再用实际的类型替换此类型参数。
泛型方法
修饰符 <T, S> 返回值类型 方法名(形参列表) {
// 方法体
}
异常
java 将所有的非正常情况分为两种:异常(Exception
)和错误(Error
),它们都继承 Throwable
。
Error 一般指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。
异常机制关键字,try、catch、finally、throw、throws
- throw:抛出一个实际的异常,可以单独作为语句使用,抛出一个具体的异常对象。
- throws:声明方法可能抛出的异常。调用该方法时,表明该方法希望它的调用者来处理该异常。
java 的异常分为两大类:Checked 异常和 Runtime 异常。
常见异常类型:
- IndexOutOfBoundsException:下标越界异常
- IllegalStateException:非法状态异常
- NumberFormatException:数字格式化异常
- NullPointerException:空指针异常
- IllegalArgumentException:非法参数异常
- …
java 7
// java 7 开始,可以使用一个catch块捕获多种类型的异常,使用竖线(|)隔开
try {
// 可能发生异常的代码
} catch (IndexOutOfBoundsException|NumberFormatException ie) {
// 处理捕获的异常
// 捕获多种异常时,异常变量默认有 final 修饰,以下代码错误
ie = new NullPointerException();
} catch (Exception e) {
// 捕获一种异常时,异常变量没有 final 修饰
} finally {
// 资源回收
// 总会被执行。如果在异常处理代码中使用System.exit(1);语句来退出虚拟机,则finally块失去执行的机会。
}
注解
每当创建描述符性质的类或接口时,一旦其中包含了重复性的工作,那就可以考虑使用注解来简化与自动化该过程。
Android 中有两种应用方式,一种方式是基于反射的,即在程序的运行期间获取类信息进行反射调用;另一种是使用注解处理,在编译期间生成许多代码,然后在运行期间通过调用这些代码来实现目标功能。
Java 中注解分为标准注解
和元注解
。
标准注解是 Java 为我们提供的预定义的注解,共有四种:@Override、@Deprecated、@SuppressWarnnings 和 @SafeVarags。
元注解是用来提供给用户自定义注解用的,共有五种(截止Java8)
- @Target:定义注解将应用于什么地方(如是一个方法或一个域)ElementType
- @Retention:定义该注解在哪一个级别可用。
RetentionPolicy枚举:
- SOURCE:注解将被编译器丢弃
- CLASS:注解在class文件中使用,但会被JVM丢弃
- RUNTIME:在运行期保留注解,可以通过反射读取注解的信息
反射
java 中获得 Class 对象通常三种方式:
- Class.forName(String className)
- 调用某个类的 class 属性来获取该类对应的 Class 对象。
- 调用某个对象的 getClass() 方法。
反射可以获取哪些信息?
- 获取指定构造器
- 获取成员变量
- 获得方法
IO(输入/输出)
输入、输出流分为字节流
和字符流
。
Java的IO流使用一种装饰器设计模式
,将IO流分为底层节点流和上层处理流。
Java 7在 java.nio
新的IO API,称为 NIO 2。
File 类
package java.io;
public class File implements Serializable, Comparable<File>
// 访问文件名相关的方法
public String getName() // 返回此 File 对象所表示的文件名或路径名(如果是路径,则返回最后一级子路径名)
public String getPath() // 返回此 File 对象所对应的路径名
// 文件检测相关的方法
public boolean exists() // 判断 File 对象所对应的文件或目录是否存在
public boolean isFile() // 判断 File 对象所对应的是否是文件,而不是目录
public boolean isDirectory() // 判断 File 对象所对应的是否是目录,而不是文件
// 文件操作相关的方法
public boolean createNewFile() throws IOException
public boolean delete()
// 目录操作相关的方法
public boolean mkdir() // 试图创建一个 File 对象所对应的目录
输入流和输出流
java的输入流主要由 InputStream
和 Reader
作为基类,而输出流则由 OutputStream
和 Writer
作为基类。都是一些抽象基类,无法直接创建实例。
字节流和字符流
字节流操作的数据单元是8位的字节,而字符流操作的数据单元是16位的字符。
字节流主要由 InputStream 和 OutputStream 作为基类,而字符流则主要由 Reader 和 Writer 作为基类。
节点流和处理流
按照流的角色来分,可以分为节点流和处理流。
相关类
- FileInputStream
- FileReader
- FilterOutputStream
对象序列化
对象序列化(Serializable
):将一个对象编码成一个字节流。
java对象的序列化机制,使用序列化机制可以把内存中的java对象转换成二进制字节流,就可以把java对象存储到磁盘里,或者在网络上传输java对象。这是java提供分布式编程的重要基础。
Lambda 表达式
java 8 新增
- 新参列表。允许省略形参类型。只有一个参数时,可以省略圆括号。
- 箭头(->)。
- 代码块。只包含一条语句时,可以省略花括号。