1.接口(interface)
类与接口是并列的两个结构。
接口使用interface关键字定义。
接口中可以声明的结构:属性、方法。接口中不能声明构造器。意味着接口不能实例化。
接口中的属性都声明为 public static final 的全局常量。或者也可以省略这些关键字的修饰。
方法:jdk 7以及以前版本,接口中定义的方法都是抽象方法,声明为:public abstract的,可以省略这些关键字的修饰。jdk 8 、9 :接口中除了定义抽象方法之外,还可以定义静态方法(static)、默认方法(default)。
作用:接口,实际上可以看成是一种标准、一种规范。
java类与接口之间是实现(implements)关系,而且是可以多实现的,解决了java类的单继承性。
如果java类实现了某个、某几个接口,则需要重写接口中的所有的抽象方法,方法可以实例化。如果没有重写,则需要把该类声明为抽象类。
接口与接口之间是继承关系,而且可以多继承。
补充:
接口中的静态方法,不能被实现类直接调用,只能通过接口自己来调用。
可以通过实现类的对象来调用接口中声明的默认方法。
如果父类和接口中声明了同名同参数的方法,则子类继承父类,实现接口后,在没有重写此方法的情况下,默认调用的父类中的方法。—“类优先”原则。
接口冲突:实现类实现了两个接口,两个接口中定义了同名同参数的方法,则实现类默认情况下就报错了,要求实现类必须要重写同名同参数的方法。
格式:接口名.super.方法名;//调用接口中的方法。
package interfaceTest;
public class InterfaceTest {
}
/**
* 接口的定义
*/
interface CompareA{
public static final int NUM = 10;
int NUMBER = 10; //虽然没有写 public static final,但是系统会自动加上。
public abstract void method1();
}
interface CompareB{
int NUM1 = 20;
void method3();
}
class MyCompare implements CompareA,CompareB{
@Override
public void method3() {
}
@Override
public void method1() {
}
}
//接口的多继承性。
interface CompareC extends CompareA,CompareB{
}
2.抽象类与接口的区别?
相同点:不能实例化。
不同点:
抽象类是有构造器的,接口没有构造器。
抽象类内部可以声明属性、方法(可以声明抽象方法)等结构。
接口:jdk1.7及以前:常量+抽象方法。jdk 8 \jdk 9:静态方法、默认方法。
使用:提供抽象类的子类,重写抽象方法。类与类之间是继承关系,而且是单继承的。
提供接口的实现类,重写接口中的抽象方法。类与接口之间是实现关系,而且可以多实现。
3.内部类:
3.1内部类的使用:
一方面,作为类:
内部类可以声明属性、方法、构造器。
可以被abstract /final修饰
另一方面,作为外部类的成员;
可以被4种权限修饰符修饰。
可以调用外部类的属性、方法等结构。
可以被static修饰。
3.2内部类的分类:
成员内部类(静态内部类 vs 非静态内部类) vs 局部内部类。
3.3内部类需要掌握的知识点:
如何实例化成员内部类?
创建静态的成员内部类对象:
格式: 外部类名.内部类名 对象名 = new 外部类.内部类构造器();
对象名.内部类方法();
创建非静态的成员内部类对象:
格式: 外部类名 外部类对象 = new 外部类构造器();
外部类名.内部类名 内部类对象 = 外部类对象.new 内部类构造器();
如何在成员内部类中调用外部类的结构:属性、方法?
格式 :外部类.this.外部类的属性名/外部类的方法名;
关于局部内部类的创建使用?
较为常见的:
//返回一个实现了Comparable接口的类的对象
public Comparable getInstance(){
//写法一:提供实现了接口的内部类
class MyComparable implements Comparable{
@Override
public int compareTo(Object o ){
return 0;
}
}
return new MyComparable();
}
public Comparable getInstance(){
//写法二:返回接口的匿名实现类的匿名对象。
return new Comparable(){
@Override
public int compareTo(Object o ){
return 0;
}
};
}
public void onCreate(){
//针对于某个视图提供监听器
view.setOnClickListener(new View.OnClickListener(){
public void onClick(){
//内容
}
});
}
4.Java异常
Rrror :Java虚拟机无法解决的严重问题。如:JVM系统内部错误、资源耗尽等严重情况。比如:StackOverFlow 和OOM(OutOfMemoryError)。一般不编写针对性的代码进行处理。
public static void main(String[] args){
//1.java.lang.StackOverFlow:栈溢出
//main(args);
//2.OutOfMemoryError:Java heap space :堆溢出
Integer[] arr = new Integer[1024*1024*1024];
}
Exception :其它因编程错误或偶然的外在因素导致的一般性问题,可以使用针对性的代码进行处理。例如:空指针访问;试图读取不存在的文件;网络连接中断。
4.1异常的体系结构:
java.lang.Throwable
|----java.lang.Error:错误
|----StackOverFlow
|----OOM
|----java.lang.Exception:异常
|---- 编译时异常(非RuntimeException)
|---- 运行时异常(RuntimeException)
4.2解决方法:
一是遇到错误就终止程序的运行。
另一种方法是由程序员在编写程序时,就考虑到错误的检测、错误消息的提示,以及错误的处理。
捕捉错误最理想的是在编译期间,但有的错误只有在运行时才会发生。
4.3异常的处理:
过程一:“抛”。程序在正常的执行过程中,一旦出现异常,就会在相应的代码处生成相应异常类的对象,并将此对象抛出,抛给方法的调用者。一旦异常对象抛出,程序就不会再执行后面的逻辑代码。
异常对象抛出的两种情况:
自动抛出;
手动抛出:在方法内部使用throw的方式。
面试题:throw与throws的区别?
throw:异常的生成阶段:手动抛出异常对象。
throws:异常的处理方式:声明方法可能要抛出的各种异常类。
过程二:“抓”。可以理解为异常处理的方式:1.try-catch-finally 2.throws
说明:
(1)finally是可选的。
(2)try中包裹的是可能出现异常的代码。程序执行过程中,一旦出现异常,就会抛出一个异常类的对象。此异常类的对象就会在下面的catch语句中进行匹配,一旦匹配成功,就进入执行处理具体的异常处理方式。
(3)多个catch语句中的异常类型如果是子父类关系,必须将子类异常类型声明在父类异常类型的上面。
(4)一旦匹配成功某一个catch语句,执行完后,就跳出当前的try-catch结构,而不会继续匹配下面的catch。
(5)在try中声明的变量,出了其所在的一对{}之后,就不可以再被调用。
(6)catch中异常处理的常见方式:
sysout(e.getMessage());
sysout(e.printStackTrace());
(7)一旦在catch中处理了异常信息,那么程序还可以继续执行。
(8)开发中,针对于运行时异常,一般就不进行异常的处理了。针对于编译时异常,一定需要考虑异常的处理,否则编译不通过。处理后的效果,可以理解为将一个编译时异常延迟到运行是才能出现。
(9)try-catch-finally结构可以嵌套使用。
4.4finally
不管try中、catch中是否存在未被处理的异常;
也不管try中、catch中是否存在return;finally中的代码都一定会被执行。
什么样的代码会声明在finally中?
涉及到流资源、网络操作中Socket资源、数据库连接资源、必须要考虑手动关闭时,需要将这些关闭的操作,声明在finally中。
面试题:final、finally、finalize的异同。
4.5throws 的方式处理异常。
(1)格式:在方法声明的最后,使用 throws+异常类型列表的方式,将异常抛出。
(2)throws 异常类型1,异常类型2,异常类型3,…这种方式将可能产生的异常对象抛给了方法的调用者。
(3)对比异常处理方式一:
try-catch-finally:真正的将异常给处理掉了。
throws:只是将异常向上抛出,并没有从根本上将此异常处理掉。
throws适合于放在操作的中间环节。
(4)如何选择使用哪种方式处理?
如果涉及到资源的关闭等操作,需要使用try-catch-finally,而不能用throws。
在项目中,针对于某个方法的某些逻辑中涉及到的多个方法的调用中,此多个方法如果有异常,习惯上使用throws的方式,然后在该方法中,统一使用try-catch-finally结构。
父类被重写的方法如果没有抛出异常,则子类重写的方法内部如有异常,只能使用try-catch-finally。(规定)
(5)重写的规则:子类重写父类的方法抛出的异常类型不能大于父类被重写的方法抛出的异常类型。
4.6如何定义一个自定义的异常类?
(1)继承于现有的异常类。通常会继承于RuntimeException或者Exception。
(2)定义重载的构造器。
(3)提供一个全局常量:serivalVersionUID ,作用唯一标识该类。
public class MyException extends Exception{
static final long serialVersionUID = -32649683126589L;
public MyException(){}
public MyException(String msg){
super(msg);
}
}
4.7如何使用自定义的异常类?
在需要使用该异常类的位置,使用throw 抛出该异常类的对象。如 throw new MyException();