前言
这是我整理的Java笔记,分模块会陆续上齐,具体链接如下:
1.面向对象:http://www.cnblogs.com/Gabby/p/6857406.html
2.集合:
3.IO:
4.多线程:
5.JVM:
6.其他知识点:序列化,泛型,注解,异常,反射:
1.面向对象
1.1 面向对象的三大特征
1.1.1 继承
1)类的继承
(1)基本定义
Java的继承具有单继承的特点,通过关键字extends实现。父类和子类的关系:一般和特殊的关系,子类是父类的一种特殊形式,例如水果和苹果。
(2)重写
当父类的方法无法满足子类的方法时,需要重写父类的方法,使用override进行重写。
重写步骤:两同两小一大
两同:方法名相同 + 参数列表相同
两小:子类返回值类型 <= 父类返回值类型 + 子类方法声明抛出异常 <= 父类声明抛出异常
一大:子类方法访问权限 >= 父类方法访问权限
(3)super 关键字
有两个作用:
调用被子类重写的父类的方法:当覆盖方法是实例方法时,使用super;当覆盖方法为类方法时,用父类类名。
子类调用父类的构造器:super用于限定该构造器初始化的是该对象从父类继承得到的实例变量。如果是类变量,则使用父类类名。
(4)继承的缺点:
会破坏父类的封装性。子类可以直接访问父类的成员变量和方法,从而造成子类和父类的严重耦合。
(5)设计父类需要满足的规则
- 尽量隐藏父类的内部数据,尽量将成员变量设置成private;
- 不要让子类随意访问,修改父类的方法。父类作为辅助的工具方法应用private修饰;父类方法需要外部类访问,则使用public修饰;父类方法需要子类重写,则使用protect修饰;
- 尽量不要在父类构造器中调用将被子类重写的方法。
(6)派生子类需要满足的条件
- 子类是一种特殊的父类,需要满足"子类 is 父类"的关系;
- 子类需要额外增加属性,而不仅仅是属性值的改变
- 子类需要增加自己独有的行为方式(包括新增方法或重写父类的方法)
2)组合
实现类复用的手段:继承和组合。
(1)组合定义
将该类当成另一个类的组成成分,从而允许新类直接复用该类的public方法。组合把旧类对象作为新类的成员变量组合进来,用以实现新类的功能,通常需要在新类里使用private修饰被组合的旧类方法。
(2)继承和组合的区别
- 继承是对已有的类的一番改造,以此获得一个特殊的版本。就是将一个较为抽象的类改为一个满足特殊需求的类;继承表达的是"is a "的关系。
- 组合表达的是整体和部分的关系,表达的是"has a " 的关系。
1.1.2 封装
1. 定义
将对象状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
2. 良好的封装需要满足:
将对象的成员变量和实现细节隐藏起来,不允许外部直接访问;
把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。
3. 访问控制符
|
private |
default |
protect |
public |
同一个类中 |
√ |
√ |
√ |
√ |
同一个包中 |
|
√ |
√ |
√ |
子类中 |
|
|
√ |
√ |
全局范围内 |
|
|
|
√ |
1.1.3 多态
1.定义
编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现了所谓的多态。多态:相同类型的变量,调用同一个方法呈现出不同的行为特征。对象的实例变量不具备多态性。
2.编译时多态:方法重载
3.运行时多态:方法重写
1.2 类
1.2.1 类的构成
1)成员变量
(1)定义
在类中定义的变量。分为实例变量(不以static修饰的)和类变量(以static修饰的)。
(2)类变量
类变量使用static修饰,是从该类的准备阶段起开始存在,直到系统完全销毁这个类,类变量的作用域与这个类的生存范围相同;
(3)实例变量
实例变量则从该类的实例被创建起开始存在,知道系统完全销毁这个实例,实例变量的作用域与对应实例的生存范围相同。
(4)成员变量的内存运行机制
当系统第一次使用一个类时会加载这个类并初始化这个类,在类的准备阶段,系统将会为该类的类变量分配内存空间并指定默认初始值。当类初始化完成后,系统会为该类分配一块内存区,该内存区包含了类变量的内存,当系统创建一个对象时,实例变量是在创建实例时分配内存空间并指定初始值的。
(5)局部变量的初始化和内存中的运行机制
局部变量是在方法中定义的变量。局部变量定义后,必须经过显式初始化后才能使用,系统不会为局部变量执行初始化,局部变量总是保存在其所在方法的栈内存中。如果局部变量是基本类型的变量,则直接把这个变量的值保存在该变量对应的内存中;如果局部变量是引用类型的变量,则这个变量里存放的是地址,通过该地址引用到堆中该变量实际引用的对象或数组。
栈内存中的变量无须系统垃圾回收,往往随着方法或代码块的运行结束而结束。
2)方法
(1)方法的所属性
static修饰的方法属于类;没有static修饰的方法属于对象。
(2)java中的参数传递机制:
只有一种传递方式:值传递。将实际参数值的副本传入方法内,而参数本身不会受任何影响。当传递的是基本类型的时候就传递值;当为对象时,则传递对象的引用地址值。
(3)方法重载:两同一不同
两同:同一类中 + 方法名相同
一不同:参数列表不同。
3)构造器
(1)定义
特殊的方法,用于创建实例时执行初始化。初始化块是构造器的补充
(2)构造器重载
使用this关键字调用本类的构造器
4)初始化块
(1)定义
对Java对象进行初始化操作。
定义方法:
[修饰符] {
//初始化块的可执行代码
}
修饰符只能是static.
(2)静态初始化块:使用static修饰的初始化块。用于对整个类进行初始化处理,一般是对类变量执行初始化处理。
(3)类的初始化阶段:
类初始化:
执行最顶层父类的静态初始化块
......
执行子类的静态初始化块
对象初始化:
执行最顶层父类的初始化块
执行最顶层父类的构造器
......
执行子类的初始化块
执行子类的构造器
1.3 不可变类
1.定义
创建该类的实例后,该实例的实例变量是不可改变的。包装类,java.lang.String都是不可变类。
2.创建自定义的不可变类规则:
(1)使用private和final修饰该类的成员变量
(2)提供带参构造器,用于根据传入参数来初始化类里的成员变量
(3)仅为该类的成员变量提供getter方法
(4)如果有必要的话,重写Object类里的equals和hashcode方法
3.String不可变类的好处
(1)只有当字符串是不可变时,字符串池才有可能实现,字符串池的实现可以在运行时节约很多堆空间,因为不同的字符串变量都指向池中的同一个字符串。
(2)因为字符串是不可变的,所以是线程安全的。
(3)类加载器要用到字符串,不可变类提供了安全性,以便被正确的类加载
(4)因为字符串是不可变的,所以在它创建的时候hashcode被缓存,不需要重新计算。
1.4 抽象类和接口
1.4.1 抽象类
(1)定义
某一个父类只知道其子类应该包含怎样的方法,但无法准确地知道子类如何实现这些方法。只有方法签名,没有方法实现。抽象类和抽象方法使用abstract修饰。抽象类中可以没有抽象方法。
(2)使用规则
- 抽象类和抽象方法必须用abstract修饰,抽象方法不能有方法体。
- 抽象类不能实例化,无法用new来调用抽象类的构造器创建实例
- 抽象类可以包含成员变量,方法(普通方法和抽象方法都可以),构造器,初始化块,内部类(接口,枚举)5种成员,主要用于其子类调用
- 含有抽象方法的类只能定义成抽象类
1.4.2 接口
(1)定义
抽象类的特殊形式,接口不能包含普通方法,接口中所有方法都是抽象方法。使用interface修饰
(2)特征
- 修饰符:可以用public或省略,省略则默认采用包权限访问控制符。
- 一个接口可以继承多个父接口,但接口只能继承接口,不能继承类。
- 接口中不能包含构造器和初始化块定义;接口中可以包含成员变量(只能是静态变量),方法(只能是抽象实例方法,类方法或者默认方法),内部类(包含内部接口,枚举);
- 静态常量会自动添加static final 修饰符;
- 接口中的方法只能用public修饰,不能有实现。类方法和默认方法必须有实现。
(3)作用:被类实现,implements.
1.4.3 抽象类和接口的区别
(1)设计目的
- 接口是多个模块间的耦合标准,类似于系统的“总纲”;
- 抽象类作为系统中多个子类的共同父类,它所体现的是一种模板式设计。可以当做中间产品,这个中间产品已经实现了系统的部分功能,但是不能当成最终产品。
(2)用法的不同
- 方法:接口只能包含抽象方法,静态方法和默认方法,不能为普通方法提供实现;抽象类完全可以包含抽象方法。
- 变量:接口中只能定义静态变量,不能定义普通成员变量;抽象类中既能定义静态变量,也能定义普通成员变量。
- 构造器:接口中不能包含构造器;抽象类中能包含构造器。
- 初始化块:接口中不能包含初始化块;抽象类中能包含初始化块。
- 一个类只能单继承;一个接口能多继承。
1.5 内部类
(1)定义
定义在一个类内部的类。
(2)作用
- 内部类提供了更好的封装,可以把内部类隐藏在外部类之内,不允许同一个包中的其他类访问该类;
- 内部类可以直接访问所在类的外部类的私有数据;外部类不能访问内部类的实现细节;如果外部类需要访问非静态内部类的成员,则必须显示创建非静态内部类对象来调用访问实例成员。
- 匿名内部类适合于创建那些仅需一次使用的类。
(3)特性
内部类的修饰符可以用private,protected,static.内部类上一级是类,有4个作用域:同一个类(private),同一个包(不使用),父子类(protected),任何位置(public)。
非静态内部类不能拥有静态成员。
1.5.1 静态内部类
(1)定义
使用static修饰一个内部类,则这个内部类属于外部类本身。
(2)特性
- 静态内部类既可以包含静态成员,也可以包含非静态成员;
- 静态内部类只能访问外部类的静态成员;
- 静态内部类寄生在外部类的类本身中,只持有外部类的类引用。
- 静态内部类是外部类的一个静态成员,因此外部类的所有方法,初始化块都可以使用静态内部类来定义变量,创建对象等。
- 外部类可以使用静态内部类的类名作为调用者来访问。
1.5.2 局部内部类
定义在方法中
局部内部类不能使用访问控制符和static修饰符修饰
1.5.3 匿名内部类
(1)定义
适合创建只需要一次使用的类。
(2)规则
- 匿名内部类必须继承且最多只能继承一个父类或实现一个接口;
- 匿名内部类不能是抽象类,不能定义构造器。
(3)创建方法
需要创建某个接口类型的对象:
new 实现接口| 父类构造器{
类体部分
}
1.6 关键字
1.6.1 static
(1)作用
用于区分成员变量,方法,内部类,初始化块这四种成员属于类本身还是属于实例。
(2)特征
static修饰的成员不能访问没有static修饰的成员;
static修饰成员则表明它属于这个类本身,称为类变量或者类方法;
1.6.2 this 与 super
(1)this
作用:指向调用该方法的对象。让类中的一个方法去访问该类的实例变量或方法。
用法:在构造器中使用表示引用该构造器正在初始化的对象;在方法中引用表示调用该方法的对象。
(2)super
使用:在子类中调用父类被覆盖的实例方法;super用于构造器表示该构造器初始化的是该对象从父类继承得到的实例变量。
(3)this 和 super的区别
super调用其父类的构造器;this调用同一类中重载的构造器。
1.6.3 final
(1)定义
表示不可以改变,不希望子类继承父类的某一个方法。
(2)作用
用于修饰类,变量和方法,用以表示类,变量和方法不可变,一旦赋初始值就不能改变。
(3)用法
修饰成员变量:类变量:必须在静态初始化块或者在声明时指定初始值;实例变量:必须在非静态初始化块或者声明变量或者构造器中使用;
修饰局部变量:声明时指定初始值。
(3)特性
- 用final修饰的成员变量需要在声明处或者构造器或者初始化块进行赋值;必须由程序员显式地指定初始值。
- final修饰基本类型需要值保持不变,不可以重新赋值;final修饰引用类型只需要地址保持不变,可以改变引用类型变量所引用对象的内容。
- final方法不希望子类重写父类的某个方法,但是可以被重载;方法使用public则不可以重写,使用private则可以定义一个一模一样的方法。
- final修饰的类不可以有子类。
1.7 其他
1.7.1 包装类
(1)来源
为8种基本数据类型分别定义了相应的引用类型。类名是基本类型的第一个字母大写。包装类的实例是引用类型。为什么要装箱:因为面向对象的思想,万物皆是对象
(2)自动装箱和自动拆箱
自动装箱:一个基本类型可以直接赋给对应的包装类变量或者赋值给Object变量
自动拆箱:允许直接把包装类对象赋给给定的基本类型变量。
(3)特性
Integer:系统把-128~127之间的整数自动装箱成Integer实例,并放入名为cache的数组中缓存起来。
1.7.2 String,StringBuffer,StringBuilder
String:字符序列不可变;会产生很多
StringBuffer:字符序列可变,线程安全但性能不高;使用synchronized.
StringBuilder:字符序列可变,线程不安全但性能略好
1.7.3 == 和 equals
==:基本类型且是数值类型,值相同返回true;引用类型对象指向同一个对象时返回true;
equals:常量池中字符串相同返回true.