1、工厂方法
什么是工厂方法?
通过方法调用的方式获取到对象
应用场景:
1)使用者无法直接创建对象,创建对象太复杂 用工厂会省事(手机)(单例)
2)使用者不想参与对象的创建过程
抽象类和接口的比较
2、内部类
类的成员
属性:描述事物的特征
方法:描述事物的行为
伪成员:构造器、语句块
内部类
什么是内部类?
把一个类声明在另一个类的内部,前面的类称为内部类,后面称为外部类
回忆变量
变量按照位置来分
1、成员变量(number variable):声明在类中方法外的变量,范围大,寿命长
1)类变量:有static修饰,隶属于类模板,寿命永久,存储在堆中的方法区
2)实例变量(local variable ):没有static修饰,寿命和对象一样长,存储在堆中的GC区
2、局部变量:声明在方法中的变量,范围小,寿命短,存储在栈区 随方法的压栈入栈
内部类的分类
1、成员内部类:声明在类中方法外的内部类
1)嵌套类 : static修饰的, 没有强烈依赖, 和外部类同级别
使用和内部类无区别
class Outer{
public static class Inner2{//嵌套类,不能直接使用外部类的对象的成员
public static int no = 10;
public static void test4(){//在嵌套类中创建了一个静态方法
System.out.println("static test4()...");
}
private String name = "嵌套类";
public Inner2(){//这是嵌套类的无参构造器
System.out.println("inner2()...");
}
public void test3(){//在嵌套类中创建了一个非静态方法
System.out.println("test3()...");
//System.out.println(Outer.this.name);//不能直接使用外部类的对象的成员
System.out.println(name);
}
}
}
public static void main2(String[] args) {
Outer.Inner2.test4();//可以直接调用嵌套类中的静态方法
// Outer.Inner2.test3();//静态环境中不能直接调用非静态方法
System.out.println(Outer.Inner2.no);//可以直接调用嵌套类中的静态属性
Outer.Inner2 inner2 = new Outer.Inner2();//可以创建嵌套类的对象
inner2.test3();//利用这个嵌套类对象去调用它的非静态方法
}
2)普通内部类 : 没有static修饰的, 隶属于外部类对象
在内部类对象中可以随意使用外部类对象的成员,用途是代替普通的对象关联
class Outer{
private String name = "外部类";
protected class Inner1{//普通内部类,隶属于外部类对象
private String name = "我是内部类";
//普通内部类不允许普通静态成员,为什么呢???
//因为加了static会同时隶属于类和对象,两者的修改都会引起它的变化,会发生矛盾
// public static int id = 2;
public int id3;
public static final int id1 = 3;//如果是静态的只能是由final修饰的,因为被final修饰的具有唯一性,不会因外部类的改变而去改变
public Inner1(){
System.out.println("Inner()....");
}
public void test1(){
//内部类和外部类如果有同名成员,必须加限定
System.out.println(this.name);//就近原则
System.out.println(Inner1.this.name);//就近原则,可以加限定 也可不加限定
System.out.println(Outer.this.name);//外部类的this必须加限定
}
}
}
public static void main1(String[] args) {
Outer outer = new Outer();
outer.teat2();
//直接创建内部类对象,通过外部类对象.new
Outer.Inner1 oi1 = new Outer().new Inner1();
oi1.test1();
}
普通对象关联和内部类的区别
内部类是更深入更夸张的对象关联,内部类关联外部类,用途是代替普通的对象关联,使对象关系密切(互相利用)
对象关联,只能使用关联对象的公共部分
内部类不如对象关联
2、局部内部类 : 声明在方法中的内部类
1)普通局部内部类
2)匿名内部类(超重点):临时要使用一个接口的实现子类对象, 用完即废.
父类 引用 = new 父类() {
类体就是父类的子类的类体;
};
99.99%的情况下是配合接口使用, 接口中通常也只有一个抽象方法.
接口 引用 = new 接口() {
类体就是接口的实体子类的类体, 必须实现接口中的所有抽象方法
}
使用场景
懒得正式写一个具体子类, 实现接口.
创建的对象绝对单例
只能多态使用
注:$表示内部类和外部类的关系
interface I7{
void hello(String s);
}
public static void main(String[] args) {
Object o1 = new Object();//创建对象
System.out.println(o1);
Object o2 = new Object() {};//匿名内部类,它是Object的匿名子类
System.out.println(o2);
//这样写省略了具体子类的声明,适用于对象的一次性创建和使用
I7 i7 = new I7() {
//类体部分就是接口的实现子类的类体
@Override
public void hello(String s) {
System.out.println("hi"+s);
}
};
i7.hello("fdasf");
}
创建内部类对象
测试类中不能省略限定
局部变量不能加权限修饰符
3、枚举(enumeratiion)
枚举是什么?
枚举是对象可数的特殊类型,使用enum关键字
枚举类型可以创建对象吗?
枚举类型不可创建对象,因为底层把构造器封装了
获取枚举对象的三种方式
1)直接获取 用点
2)名字获取,根据给定的常量对象名获取相应的对象的引用
3)获取保存所有枚举对象的对象数组
枚举的方法
用switch进行枚举可能的情况
枚举中的构造器一定私有,因为其不能创建对象
4、异常处理
什么是异常处理?
异常:运行中出现的非正常状况,如果不处理,程序崩溃
注意:开发过程中语法错误,逻辑错误不是异常!
异常分类
1、按程度来分
1)Error:严重错误。java虚拟机无法解决的严重问题。
2)Exception:一般问题。因编程错误或偶然意外,造成的异常
2、按照处理方式来分
1)受检异常:编译时异常。程序中必须接受检查和处理的异常,如不处理,编译出错
Exception及其子类(RuntimeException除外):不容忽视的一般问题
2)非受检异常:运行时异常。可以不接受检查和处理的异常,如果不处理,编译不出错,但运行时会出错
Error及其子类:太严重,
RuntimeException及其子类:太轻微,太常见
无论是受检还是非受检异常,都会导致程序崩溃,所以都应该处理
异常的堆栈式抛出机制
异常处理方式
适用于所有异常
1、捕获
try{
可能抛出异常的语句;
}catch(异常类型 引用){
如果语句中真的抛出了这个异常类型的对象,在这里就捕获了
}....{
}catch(Exception e){
//确保万无一失
}finally{
无论前面try catch 中发生了什么,都要必须要执行的语句;
主要功能是在这里释放GC区外的硬件资源
}
异常处理中可以有多个catch吗?
异常处理其实保护的是后面的,可以有多个catch ,以防止类型不全,也可以用Exception,这个超级无敌万能夹,确保万无一失,但是还是用多个不同的catch比较好
好处:把异常的破坏所波及的范围缩小
什么是finally?为什么要有finally?
finally 是无论前面try catch 中发生了什么,都要必须要执行的语句;
因为其主要功能是释放GC区外的硬件资源,否则会形成资源泄露
这个语句可以拦截finally
public class TestException {
public static void main(String[] args) {
System.out.println("main begin");
try{
int n = Integer.parseInt(args[0]);
int m = Integer.parseInt(args[1]);
System.out.println(n/m);
}catch (NumberFormatException e){
System.out.println(e.getMessage());
}catch (ArithmeticException e){
System.out.println(e.getStackTrace());
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}catch (Exception e){
e.printStackTrace();
}
System.out.println("main end");//核心代码
}
}
唯一能拦截finally的语句
组合方式:
try catch
try catch finally
try finally
理解finally的小例子
总结
今天学习的内容:
1)工厂方法;
2)内部类;
3)枚举;
4)异常处理