Object是java中已有的一个所有类的父类。也称为根类,你可以把它理解为java中的上帝。java中的类都是直接或者间接继承自object类。
该类的出现:是封装了所有对象都具备的方法。
所有对象都具备方法有哪些呢?
boolean equals(Object obj):对对象进行比较。该方法的默认是比较内存地址,所以很多对象都对该方法进行复写。建立对象的自己比较是否相同的方式。
StringtoString():将对象变成字符串:格式: 对象类型@对象哈希值,但是这个结果没什么意义,所以,该方法一般也会被覆盖,建立该对象的自己特有的对应字符串的表现形式。
inthashCode():获取每一个对象的哈希值,可以理解为是地址值,是通过哈希算法完成的。
ClassgetClass():获取一个对象的所属字节码文件对象。
void finalize():垃圾回收器调用的垃圾回收方法。释放资源和释放内存。
例子1:Object类具备的方法实例演示。
- package cn.itheima.day15;
- class Demo {
-
-
-
-
-
-
- private int num;
- public Demo(int num) {
- this.num = num;
- }
-
-
-
-
-
-
- public boolean equals(Object obj){
- if(this==obj)
- return true;
- if(!(obj instanceof Demo))
- return false;
- Demo d = (Demo)obj;
- if(this.num == d.num){
- return true;
- }
- return false;
- }
-
- public String toString(){
- return "Demo's num="+num;
- }
- }
- class Person{
- }
- public class ObjectDemo {
- public static void main(String[] args) {
- Demo d1 = new Demo(5);
- Demo d2 = new Demo(7);
- Demo d3 = new Demo(5);
- System.out.println(d1);
- System.out.println(d2);
- System.out.println(d3);
- System.out.println(d1.hashCode());
-
-
-
-
- Class clazz = d1.getClass();
-
- System.out.println(clazz.getName());
-
- Person p = new Person();
- System.out.println(p.getClass().getName());
- System.out.println(d1.equals(d2));
- System.out.println(d1.equals(d3));
-
-
-
-
-
-
-
-
-
-
-
- }
- }
例子2:垃圾回收器finalize()方法的实例演示。
- package cn.itheima.day15;
- class Demo1{
- public void finalize(){
- System.out.println("finalize run");
- }
- }
-
-
-
-
-
- public class FinalizeDemo {
- public static void main(String[] args) throws InterruptedException {
- new Demo1();
- new Demo1();
- new Demo1();
- Thread.sleep(10);
- System.gc();
- }
- }
内部类:又叫内置类或者嵌套类。将类定义在另一个类中,该类就是内部类。类中定义的类就是内部类。其实类的定义位置发生了一点小变化。
访问方式:
内部类可以直接访问外部类中的成员。
外部类想要访问内部类,需要建立内部类对象。
例子1:定义一个内部类的应用实例。
- package cn.itheima.day15;
- class Outer{
- private int num = 3;
- class Inner{
- void show(){
- System.out.println("inner show run--"+num);
- }
- }
- public void method(){
- Inner in = new Inner();
- in.show();
- }
- }
- public class InnerClassDemo {
- public static void main(String[] args) {
- Outer out = new Outer();
- out.method();
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
有A类和B类,当A类想要直接访问B类中的成员,而B类又需要建立A类的对象,来访问A类中的成员。这时,就将A类定义成B类的内部类。比喻:孙悟空和铁扇公主。孙悟空到了公主肚子中,就成了内部类。
class B{
class A{}
}
什么时候定义内部类呢?
当分析一个事物时,该事物的内部还有具体的事物,这个具体的事物在使用该事物中的其他成员。这时就将这个具体的事物用内部类来描述。
比如:人体是一个类,人体有心脏,心脏的功能在直接访问人体的其他内容。这时就将心脏定义在人体类中,作为内部类存在。
而且内部类通常都不会直接对外提供,都会封装到外部类中,外部了一般会通过对外提供方法的形式对其进行访问内部类只有默认权限修饰符,或者 public修饰符时,可以被外部类直接访问到。
Outer.Innerin = new Outer().new Inner();
注意要保证的是该内部类必须定义在外部类的成员位置上。
格式:外部类名.内部类名 变量 = 外部类对象.内部类对象;
但是一般不会这么用,因为内部类都会被外部类隐藏,通常都是外部类提供方法获取内部类的对象。这样可以对获取对象可控。通常内部类都会被private私有化。
Outer.Inner in = new Outer().new Inner();
in.show();
当内部类中如果有静态成员时,该内部类也必须是静态的。而静态内部类只能访问外部类中的静态成员。
在执行static内部类方法时,两种情况。
1,内部类静态,但是方法没静态。该方法需要被对象调用执行。
Outer.Inner in = new Outer.Inner();//产生了一个静态内部类对象。
in.show();
2,内部类静态,而且方法也是静态的。静态内部类随着对象的加载就已经存在了,静态方法随着内部类的加载也存在了。这时是不需要对象的。
Outer.Inner.show();
例子2:内部类中的静态和非静态的方法以及变量访问方式。
- package cn.itheima.day15;
- class Outer2{
- private int num = 4;
- static int num2 = 8;
- static class Inner{
- static void show(){
- System.out.println("show run::"+num2);
- }
- }
-
-
-
-
- }
- public class InnerClassDemo2 {
- public static void main(String[] args) {
-
-
-
-
-
-
- Outer2.Inner.show();
- }
- }
非静态的内部类之所以可以直接访问外部类中的成员,那是因为内部类中都持有一个外部类对象引用:外部类名.this
静态的内部类之所以可以直接访问外部类中的静态成员,其实持有的是外部类名。记住只有内部类定义在成员位置上,才可以有这些成员修饰符。
例子3:定义在成员位置上的内部类的修饰符用法实例演示。
- package cn.itheima.day15;
- class Outer3{
- int num = 4;
- static int num2 =9;
- class Inner{
- int num = 8;
- void show(){
- int num = 3;
- System.out.println("show run::"+num);
- System.out.println("show run::"+this.num);
- System.out.println("show run::"+Outer3.this.num);
- }
- }
- static class Inner2{
- static void function(){
- System.out.println("show run::"+num2);
- }
- }
- public static void method2(){
- Inner2 in2 = new Inner2();
- in2.function();
- }
- public void method(){
- Inner in = new Inner();
- in.show();
- }
- }
- public class InnerClassDemo3 {
- public static void main(String[] args) {
- Outer3 out = new Outer3();
-
- out.method2();
- }
- }
内部类定义在类中的局部位置。内部类定义局部位置上,只能访问该局部中的被final修饰的常量。
例子4:内部类定义在类中的局部位置上。
- package cn.itheima.day15;
-
-
-
-
-
- class Outer4{
- int num = 4;
- public void method(){
- final int num2 = 8;
- class Inner{
- void show(){
- System.out.println("show run::"+num2);
- }
- }
- new Inner().show();
- }
- }
- public class InnerClassDemo4 {
- public static void main(String[] args) {
- new Outer4().method();
- }
- }
匿名内部类:就没有名字的内部类。
好处:简化了内部类的书写。
前提:内部类必须要继承或者实现一个外部类或外部接口
匿名内部类的格式:
new 父类名或者接口(){
里面定义该父类或者接口的子类成员。
}
匿名内部类其实就是一个子类匿名对象。这是一个带有内容的对象,这个对象有点胖。
例子5:匿名内部类的实例演示。
- package cn.itheima.day15;
-
-
-
-
- abstract class AbsDemo{
- abstract void show();
- }
- class Outer5{
- private int num = 4;
-
-
-
-
-
-
- public void method(){
- new AbsDemo() {
- @Override
- void show() {
- System.out.println("num==="+num);
- }
- }.show();
- }
- }
- public class NiMingInnerDemo {
- public static void main(String[] args) {
- new Outer5().method();
- }
- }
例子6:匿名对象的面试题。
- package cn.itheima.day15;
-
- interface Inter{
- void show1();
- void show2();
- }
- class Outer6{
-
-
-
-
-
-
-
-
-
- public void method(){
- Inter in = new Inter(){
- public void show1(){
- System.out.println("show1 run");
- }
- public void show2(){
- System.out.println("show2 run");
- }
- };
- in.show1();
- in.show2();
- }
- }
- class Demo2{
- void function(){
- System.out.println("demo funtion run");
- }
- }
- public class NiMingInnerDemo2 {
- public static void main(String[] args) {
-
-
-
- new Demo2(){
- void function(){
- System.out.println("heima");
- }
- }.function();
- }
-
-
-
-
-
-
-
-
- Object obj = new Object(){
- void method(){
- System.out.println("method run");
- }
- };
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
什么时候使用匿名内部类呢?
当函数的参数是一个接口类型的引用,而且该接口中的方法不超过3个。这时可以给这个函数传递一个匿名内部类实际参数进入。简化书写。
例子7:匿名内部类的实例演示。
- package cn.itheima.day15;
- interface Inter2{
- void show();
- }
- class Outer7{
-
- static Inter2 method(){
- return new Inter2(){
- public void show(){
- System.out.println("show run");
- }
- };
- }
- }
- public class NiMingTest {
- public static void main(String[] args) {
-
-
-
-
-
-
-
-
- function(new Inter2(){
- public void show(){
- System.out.println("inner show run");
- }
- });
- }
- public static void function(Inter2 in){
- in.show();
- }
- }
异常:就是程序运行时出现的不正常情况。
例子8:异常的演示代码。
- package cn.itheima.day15;
- class Demo4{
- public int div(int a,int b){
- return a/b;
- }
- public void method(){
- int[] arr = new int[3];
- System.out.println(arr[3]);
- }
- }
- public class ExceptionDemo {
- public static void main(String[] args) {
- Demo4 d = new Demo4();
-
-
-
- d.method();
- System.out.println("over");
- }
- }
发现,当调用者往里传入了除数0,就发生。编译通过(语法没错误),而运行失败的情况。出现一个ArithmeticException:/ by zero 一个异常。运行提前终止,后续的代码就不会在执行了。
其实异常就是程序中出现的问题:这个问题包括:问题的名称,问题的信息,以及问题出现的位置。这个问题中内部中的有很多,按照面向对象将这个问题封装成了对象。
通过if判断形式,也可以对问题进行处理。但是这样会导致,问题处理代码和正常的业务流程代码都定义在了一起,不便于阅读,当把问题封装成对象后,当该问题产生后,可以让程序进行跳转有一个特定的区域对问题进行处理。
这样,异常的出现可以是问题处理代码和业务逻辑代码相分离,提高了程序的阅读性。Java对常见的一系列都进行了描述,并进行了对象的封装。
查阅一下API。发现异常中很多子类。
因为常见问题很多,就对这些问题进行描述并建立了体系。
异常问题分为两大类:
1,可以处理的问题。
一般用Exception(异常)来进行描述。这个问题可以有针对性的代码进行处理。
2,重大错误问题,
用Error进行描述。这个问题发生后,一般不编写针对的代码进行处理,而是要对程序进行修正。
通常都有JVM抛出的问题。
这两个派系,他们的子类都有一个共同特征:所有子类名成结尾都是以父类名作为后缀。
问题:就如同疾病:可以治愈的疾病。Exception也有绝症。Error.无论错误还是异常,他们都有:名称标识,同时也有问题的信息、问题出现的位置。
既然有这样的共性可以向上继续抽取。它们都有了一个共同的父类Throwable,该父类中就定义了该体系中最共性的方法.
String getMessage():获取异常的信息。
String toString():将异常对象变成字符串。其实该类是覆盖Object类中的toString();
void printStackTrace():打印异常在内存中的详细信息。直接打印到控制台。
异常的处理。有两种:
1,将异常抛出。
2,使用java中指定的代码块进行自定义处理。
try{
需要检测异常的代码;
}
catch(异常类 变量){
异常处理代码;
}
finally{
一定会被执行的代码;
}
例子9:异常处理的实例演示。
- package cn.itheima.day15;
- class Demo5{
- public int div(int a,int b){
- return a/b;
- }
- }
- public class ExceptionDemo2 {
- public static void main(String[] args) {
- Demo5 d = new Demo5();
- try {
- int num = d.div(4, 0);
- System.out.println("num="+num);
- } catch (Exception e) {
- System.out.println("有异常存在!");
- System.out.println("message:"+e.getMessage());
- System.out.println("toStrig:"+e.toString());
- e.printStackTrace();
-
-
- }
- System.out.println("over");
- }
- }
处理异常:
要么throws(抛出异常),要么try…cacth。到底是try…cacth好呢?还是throws好呢?
原则:如果该功能内部可以将问题处理,用try…cacth,如果处理不了,交由调用者处理,这时用throws。
例子10:try…cacth和throws(抛出异常)实例演示。
- package cn.itheima.day15;
-
-
-
-
-
-
-
-
- class Demo6{
- public int div(int a,int b) throws Exception{
- return a/b;
- }
- }
- public class ExceptionDemo3 {
- public static void main(String[] args) {
- Demo6 d = new Demo6();
- try {
- int num = d.div(4, 0);
- System.out.println("num="+num);
- } catch (Exception e) {
- System.out.println("发生异常!");
- }
- System.out.println("over");
- }
- }
如果使用到了一个声明了异常的功能时,必须要对应的抛出throws或者try的处理方式。否则编译失败。但是有一种特殊情况。当功能上声明的异常是一个特殊的异常子类时,这时该功能被调用,可以不用任何处理方式,一样可以编译通过。这个特殊异常就是Exception中的一个子类RuntimeException。(运行时异常)
异常分两种:
1,编译时被检测的异常.包括除了Exception子类RuntimeException以外的所有异常。如果在函数上声明,如果调用时,没有处理方式,编译会编译。而且这种异常需要有针对性的处理方式。是可被处理的。
2,编译时不被检测的异常:包括RuntimeException以及子类。
该异常也称为运行时异常,如果功能声明了此异常,调用者可以不用任何处理方式。通过该异常不需声明。如果发生,就是需要程序停止,对代码进行修正。
例子11:运行时异常的实例演示。
- package cn.itheima.day15;
- class Demo7 {
- public int div(int a,int b) throws RuntimeException{
- return a/b;
- }
- }
- public class ExceptionDemo4 {
- public static void main(String[] args) {
- Demo7 d = new Demo7();
- int num = d.div(4, 0);
- System.out.println("num="+num);
- System.out.println("over");
- }
- }
在自定义项目中,也会有很多问题发生,这些问题,有可能是项目特有问题,是没有被java所描述的。那么这时,就需要我们继续按照java的异常思想,将特有问题也封装成对象。自定义异常。将特有的问题进行描述,并封装成对象。
//在下面示例中,要求,除数不可以为负数。
这种问题java没有提供先有的描述方式。所以只有自己进行描述。
自定义异常的步骤:
定义一个类对问题描述。要想成为异常,必须继承异常类才可以。这样才可以成为异常体系中的一员。其实最根本原因:异常体系和其他对象的不同之处在于异常体系都具备可抛性。
异常的类和对象都可以被两个关键字所操作,而且只有异常体系具备这个特点,哪两个关键字呢?throws和throw
当函数内容通过throw抛出了一个编译时检测的异常。必须要有处理方式。要么try,要么throws。
处理调用出现异常的函数的原则:
调用了声明异常的函数,处理时,对方声明什么异常,我们就处理什么异常。自定义异常可以继承Exception,也可以继承RuntimeException。如果该问题发生,不需要声明需要是调用修正代码,那么就需要继承RuntimeException。
throws和throw的区别:
throws用在函数上,用于声明该功能容易出现问题。可以调用者进行处理的。
throw用在函数内,用于抛出指定的具体异常对象。
throws后面跟的是异常类。可以跟多个,中间用逗号隔开。
throw后面跟的是异常对象。
只有异常体系的类和对象才可以被这两个关键字所操作。
例子12.自定义异常类的实例演示。
- package cn.itheima.day15;
- class FuShuException extends RuntimeException{
- private int num;
- public FuShuException(String msg,int num) {
- super(msg);
- this.num = num;
- }
- public int getNum(){
- return num;
- }
- }
- class Demo8 {
- public int div(int a,int b) {
-
-
- if(b<0)
-
-
- throw new FuShuException("除数不能为负数", b);
- return a/b;
- }
- }
- public class ExceptionDemo5 {
- public static void main(String[] args) {
- Demo8 d = new Demo8();
-
- int num = d.div(4, -1);
- System.out.println("num="+num);
-
-
-
-
-
-
- System.out.println("over");
- }
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
例子13.异常的处理的实例演示。
finally代码块。finally代码块中定义是用于关闭资源的代码。
举例:
操作数据库。无论数据是否添加成功,都需要进行数据库的关闭动作,因为关闭动作可以释放数据库的资源。提高数据库的性能。
void add(){
try{
连接数据库。
添加数据。
}
catch(SQLExceptione){
异常处理方式。
}
finally{
关闭数据库
}
}
Try…catch…finally在使用的时候,try可以和catch相结合使用,可以对应多个catch。如果没有catch,try可以和finally结合使用。
如果功能中,出现了编译时“需要被检测的异常”字样时,如果没有被catch,就必须要throws声明,否则编译失败
记住:只有catch是处理异常的代码块.
void show()throws Excpetion{
try{
code();//使用了底层资源。
thrownew Excpetion();
}
finally{
资源释放。
}
}
例子14. Finally用法的实例演示。
- package cn.itheima.day15;
- class Demo9{
- public int div(int a,int b) throws Exception{
- return a/b;
- }
- }
- public class ExceptionDemo6 {
- public static void main(String[] args) {
- Demo9 d = new Demo9();
- try {
- int num = d.div(4, 0);
- System.out.println("num="+num);
- } catch (Exception e) {
- System.out.println(e.toString());
-
- System.exit(0);
- }finally{
- System.out.println("finally run");
- }
- System.out.println("over");
- }
- }
异常的处理细节:
1,当子类覆盖父类时,如果父类的方法抛出了异常,那么子类覆盖父类要么不抛异常,要么抛出该异常或者该异常的子类。
2,如果父类抛出了多个异常,子类覆盖父类时,只能抛出这些异常子集。
简单一句话:子类只能抛父类的异常或者异常的子类或子集。子类不可以抛出父类没有的异常。
例子15.异常处理的细节实例。
- package cn.itheima.day15;
-
-
-
-
-
-
-
- class AException extends Exception{
- }
- class BException extends AException{
- }
- class CException extends Exception{
- }
- class Fu{
- void show() throws AException{
- System.out.println("Fu");
- }
- }
- class Tool{
- void method(Fu f){
- try {
- f.show();
- } catch (AException e) {
- e.printStackTrace();
- }
- }
- }
- class Zi extends Fu{
- void show() throws AException{
- System.out.println("Zi");
- }
- }
- public class ExceptionDemo7 {
- public static void main(String[] args) {
- Tool tool = new Tool();
- tool.method(new Zi());
- }
- }
注意:如果被覆盖的方法没有异常抛出,那么子类的方法绝对不可以抛出异常。如果子类方法内还有异常发生。那么子类只能try,不能throws.
面试细节:当try对应多个catch时,如果catch的类型有继承关系,那么父类型的catch一定要放在下面.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- */
- void method()
- {
- if()
- throw new RuntimeException();
- System.out.println("haha");
- }