java面向对象
类
基本概念
- 类:对一类事物的描述,是抽象的,概念上的定义
- **对象:**实际存在的该类事物的每个个体,也称为实例
- 面向对象的3个特征:封装,继承,多态
修饰符 class 类名{
属性声明;
方法声明:
}
类的访问机制
- **在一个类中的访问机制:**类中的方法可以直接访问类中的成员变量
- **在不同类中的访问机制:**先创建要访问类的对象,再用对象访问类中定义的成员
成员变量与局部变量
成员变量 | 局部变量 | |
---|---|---|
位置 | 声明在类中 | 方法形参,代码块内,构造器内 |
修饰符 | private,public,static | 不能用权限修饰符,可以使用final |
初始化值 | 有默认初始值 | 没有,必须显式赋值 |
内存加载位置 | 堆空间,静态域内 | 栈空间 |
构造器
- 作用:给对象进行初始化
- 特征:与类名相同;不声明返回类型,不能被修饰符修饰,不能有return语句;
- 注意:
- java语言中,每个类都至少有一个构造器
- 默认构造器的修饰符与所属类的修饰符一致
- 一旦显示定义了构造器,则系统不再提供默认构造器
- 一个类可以创建多个重载的构造器
- 父类的构造器不可被子类继承
属性赋值过程
1. 默认初始化
2. 显示初始化
3. 构造其中初始化
4. 通过“对象.属性"或”对象.方法"的方式赋值
类变量和实例变量的区别
- 地址解析
类变量 | 实例变量 | |
---|---|---|
存放位置 | 方法区 | 堆内存 |
生命周期 | 随着类消失而消失 | 随着对象消失而消失 |
继承(extends)
-
java中只支持单继承,且访问属性和方法采用就近原则
-
语法
class 子类名 extends 父类名{....}
-
作用:
- 减少了代码冗余,提高代码的复用性
- 有利于功能的扩展
- 让类与类之间产生了关系,提供了多态的前提
继承中的程序执行顺序
class Father{
static String nation; // 1
static {} // 2
{} // 5
Father(){} // 6
}
class Son extends Father{
static String school; // 3
static {} // 4
{} // 7
Son(){
super();
.... // 8
}
}
Object类
- Object类是Java
java.lang
包下的核心类,Object类是所有类的父类 - 常用方法
-
clone():保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
-
getClass():final方法,返回Class类型的对象,反射来获取对象。
-
toString():该方法用得比较多,一般子类都有覆盖,来获取对象的信息。
-
finalize():该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
-
equals():比较对象的内容是否相等
-
hashCode():该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
-
wait():wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁
-
notify():该方法唤醒在该对象上等待的某个线程。
-
notifyAll():该方法唤醒在该对象上等待的所有线程。
重写与重载
对比项 | 重写(Override) | 重载(Overload) |
---|---|---|
位置 | 父类(接口)和子类之间 | 同一类内,或者父子关系中 |
方法签名 | 必须一致 | 必须不一致 |
返回值 | 必须相同 | 没要求 |
数量 | 被一个子类覆盖最多一次 | 数量无限制 |
注解 | @Override | 无 |
四种访问权限修饰符
修饰符 | 类内部 | 同一个包 | 不同一个包 | 同一个工程 |
---|---|---|---|---|
private | Yes | |||
default | Yes | Yes | ||
protected | Yes | Yes | Yes | |
public | Yes | Yes | Yes | Yes |
this关键字
- 在构造器方法中,代表当前正在构造的对象
- 在成员方法中,代表当前正在调用的对象
super关键字
- 作用:访问父类的属性和方法(eg:super.属性 或者 super.方法)
- super()必须是子类构造函数第一执行的语句,没写是默认调用super()
final关键字
所在位置 | 作用 |
---|---|
修饰类 | 该类不能在被继承,主要防止滥用继承 |
修饰方法 | 该方法不能被任何派生的子类重写 |
修饰变量 | 表示变量的值在初始化之后就不能再改变; |
static关键字
-
非static可以调用static属性和方法
-
静态方法可以调用本类中的静态方法
-
static修饰的属性具有共享性
-
java开发手则:避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。
抽象类
-
用abstract关键字来修饰一个类,这个类叫做抽象类
-
用abstract来修饰一个方法,该方法叫做抽象方法
-
只有方法的声明,没有方法的实现,以分号结束;
eg:public abstract void talk();
-
-
含有抽象方法的类必须被声明为抽象类
-
抽象类不能被实例化。抽象类是用来被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。
-
不能用abstract修饰变量,代码块,构造器
接口
- 接口是抽象方法和常量值定义的集合
- 特点:
- 接口中的所用成员变量都默认是public static final修饰的
- 接口中的所有抽象方法都默认是由public abstract修饰的
- 接口中没有构造器
- 接口采用多继承机制
- 主要用途:面向接口编程
多态
- 介绍:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
- 实现条件
- 继承:在多态中必须存在有继承关系的子类和父类。
- 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
- 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法
- 实现形式
- **基于接口实现的多态:**在接口的多态中,指向接口的引用必须是指定这实现了该接口的一个类的实例程序,在运行时,根据对象引用的实际类型来执行对应的方法。
- **基于继承实现的多态:**主要表现在父类和继承该父类的一个或多个子类对某些方法的重写,多个子类对同一方法的重写可以表现出不同的行为。
内部类
-
分类:
- 成员内部类(static成员内部类和非static成员内部类)
- 局部内部类(不谈修饰符),匿名内部类
-
成员内部类
- 成员内部类作为类的成员的角色:
- 和外部类不同,Inner class还可以声明为private或protected
- 可以调用外部类的结构
- Inner class 可以声明为static的,但此时就不能再使用外层类的非static的成员变量
- 成员内部类作为类的角色:
- 可以在内部定义属性、方法、构造器等结构
- 可以声明为abstract类 ,因此可以被其它的内部类继承
- 可以声明为final的
- 编译以后生成OuterClass$InnerClass.class字节码文件(也适用于局部内部类)
- 注意
- 非static的成员内部类中的成员不能声明为static的,只有在外部类或static的成员内部类中才可声明static成员。
- 外部类访问成员内部类的成员,需要“内部类.成员”或“内部类对象.成员”的方式
- 成员内部类可以直接使用外部类的所有成员,包括私有的数据
- 当想要在外部类的静态成员部分使用内部类时,可以考虑内部类声明为静态的
- 成员内部类作为类的成员的角色:
-
匿名内部类
new 父类构造器(实参列表)|实现接口(){
//匿名内部类的类体部分
}
- 特点:
- 必须继承父类或实现接口
- 只能有一个对象
- 只能使用多态形式应用
集合
集合的分类
- Collection接口:单列数据,定义了存取一组对象的方法的集合
- List:元素有序,可重复的集合
- Set:元素无序,不可重复的集合
- Map接口:双列数据,保存具有映射关系“key-value对”的集合
集合的常用方法
1、添加
add(Object obj)
addAll(Collection coll)
2、获取有效元素的个数
int size()
3、清空集合
void clear()
4、是否是空集合
boolean isEmpty()
5、是否包含某个元素
boolean contains(Object obj):是通过元素的quals方法来判断是否是同一个对象
boolean containsAll(Collection c):也是调用元素的equals方法来比较的。拿两个集合的元素挨个比较。
6、删除
boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
boolean removeAll(Collection coll):取当前集合的差集
7、取两个集合的交集
boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c
8、集合是否相等
boolean equals(Object obj)
9、转成对象数组
Object[] toArray()
10、获取集合对象的哈希值
hashCode()
11、遍历
iterator():返回迭代器对象,用于集合遍历
Iterator迭代器接口
- 迭代器的定义:提供一种方法访问一个容器(container)对象中各个元素,而又不需暴露该对象的内部细节
- Iteration仅用于遍历集合
- 集合对象每次调用iterator()方法都得到一个全新的迭代器对象
- Iterator接口的方法
//hasNext():判断是否还有下一个元素
while(iterator.hasNext()){
//next():①指针下移 ②将下移以后集合位置上的元素返回
System.out.println(iterator.next());
}
-----------------------------------------------
Iterator iter = coll.iterator();//回到起点
while(iter.hasNext()){
Object obj = iter.next();
if(obj.equals("Tom")){
iter.remove();
} }
- 注意:
- Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方 法,不是集合对象的remove方法。
- 如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。
- for each循环遍历
- 遍历集合的底层调用Iterator完成操作
- for each还可以遍历数组
- LinkedList和ArrayList
-
异同:二者都线程不安全,相对线程安全的Vector,执行效率高。此外,ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因为ArrayList要移动数据。
-
ArrayList在JDK1.8中像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组
-
Arrays.asList(…) 方法返回的 List 集合,既不是 ArrayList 实例,也不是Vector 实例。Arrays.asList(…) 返回值是一个固定长度的 List 集合
-
对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
异常处理
- 异常体系结构
- 运行时异常:是指编译器不要求强制处置的异常。一般是指编程时的逻辑错误,是程序员应该积极避免其出现的异常。java.lang.RuntimeException类及它的子类都是运行时异常。
- 编译时异常:是指编译器要求必须处置的异常。即程序在运行时由于外界因素造成的一般性异常。编译器要求Java程序必须捕获或声明所有编译时异常。
- try-catch-finally
try{ // 捕获异常的范围
...
}catch(ExceptionName1 e){ // 处理不同类型的异常对象
...
}finally{ // 无论catch中是否有return,语句都会被执行
...
}
-
throws(声明抛出异常)
-
如果一个方法中的语句执行时可能生成某种异常,但是并不能确定如何处理这种异常,则此方法应显示地声明抛出异常,表明该方法将不对这些异常进行处理,而由该方法的调用者负责处理。
-
重写方法不能抛出比被重写方法范围更大的异常类型。在多态的情况下,
对methodA()方法的调用-异常的捕获按父类声明的异常处理。
public class A{ public void methodA() throws IOException{} } public class B extends A{ public void methodA() throwsFileNotFoundException{} }
-
-
throw(手动抛出异常)
- 首先要生成异常类对象,然后通过throw语句实现抛出操作(提交给Java运行环境)。
-
用户自定义异常类
- 用户自己的异常类必须继承现有的异常类
- 一般地,用户自定义异常类都是RuntimeException的子类。
- 通常需要编写几个重载的构造器。
- 需要提供serialVersionUID
- 自定义的异常通过throw抛出。
- 自定义异常最重要的是异常类的名字,当异常出现时,可以根据名字判断异常类型