面向对象
Object类
Object:所有类的根类,Object是不断抽取而来的,具备着所有对象都具备的共性内容。
常用的共性内容:
equals方法
指示其他某个对象是否与此对象“相等”。
class Person
{
private int age;
Person(int age)
{
this.age = age;
}
}
class ObjectDemo
{
main()
{
Person p1 = new Person(20);
Person p2 = new Person(20);
Person p3 = p1;
System.out.println(p1==p2);
System.out.println(p1.equals(p2));
System.out.println(p1.equals(p3));//false,false,true,对象的比较是比较地址是否一致
}
}
hashCode方法
返回该对象的哈希码值
class ObjectDemo
{
main()
{
Person p1 = new Person(20);
Person p2 = new Person(20);
System.out.println(p1);
System.out.println(p1.hashCode());
}//两者输出结果表示的地址相同,不过后者是十进制,输出为827574,前者为十六进制,输出为Person@ca0b6
}
当equals方法被重写时,通常需要重写hashCode方法,hashCode的常规协定声明相等对象必须具有相等的哈希码。
getClass方法
返回此Object运行时类
class ObjectDemo
{
public static void main(String[] args)
{
Person p1 = new Person(20);
Person p2 = new Person(20);
Class clazz1 = p1.getClass();
Class clazz2 = p2.getClass();
System.out.println(clazz1==clazz2);//true
System.out.println(clazz1.getName());//Person
}
}
toString方法
返回该对象的字符串表示,它的值等于:getClass().getName()+ “@”+ Integer.toHexString(hashCode())
class ObjectDemo
{
public static void main(String[] args)
{
Person p1 = new Person(20);
System.out.println(p1);//Person@61d38,默认调用了toString(),即结果等同于p1.toString()
System.out.println(p1.getClass().getName()+"@"+Integer.toHexString(p1.hashCode()));//Person@61d38
}
}
toString方法的结果应是一个易于读懂的信息表达式,建议所有子类都重写此方法。
class Person extends Object
{
...
public String toString()
{
return "Person:"+age;
}
}
class ObjectDemo
{
public static void main(String[] args)
{
Person p1 = new Person(20);
System.out.println(p1);//Person:20
}
}
异常
体系
用异常类对问题进行描述和封装,不同的问题用不同的类进行具体的描述。将不同类的共性进行向上抽取,形成了异常体系,最终问题分成了两大类。
Throwable(可抛性):
- 一般不可处理的(Error),是由jvm抛出的严重性的问题,一般不针对性处理,直接修改程序;
- 可处理的(Exception)
- 该体系特点:子类的后缀名都是用其父类名作为后缀
凡是被throws,throw所操作的类和对象都具有可抛性。
原理&异常对象的抛出
出现异常时,虚拟机先new一个相应的对象(封装),然后用throw抛出给主函数(调用者),然而主函数没有处理方法,又转给了虚拟机,虚拟机默认处理掉,即把异常对象的信息发到控制台,让运行者看到。
插图
自定义异常
如果让一个类称为异常类,必须继承异常体系,因为这样才具有可抛性,才能被关键字throws,throw操作
class FuShuIndexException extends Exception
{
FuShuIndexException() {}
FuShuIndexException(String msg)
{
super(msg);
}
}
- 如果函数内发生了异常,函数上需要进行声明,否则编译失败;
- 调用了发生异常的函数,必须要处理(方式之一:抛出),否则编译失败;
class Demo
{
public int method (int[] arr,int index) throws FuShuIndexException//声明异常
{
if(index<0)
{
throw new FuShuIndexException("角标不能为负数");
}
return arr[index];
}
}
class ExceptionDemo
{
public static void main(String[] args) throws FuShuIndexException
{
int[] arr new int[3];
Demo d = new Demo();
int num = d.method(arr,-3);
System.out.println("over")
}
}
编译异常与运行异常
异常的分类:
- 编译时被检测异常:只要是exception和其子类都是,除了特殊子类RuntimeException体系,这种情况一般是可处理的
- 编译时不检测异常(运行时异常):RuntimeException体系和其子类,不管是否处理编译都能通过。这种情况更多是调用者的原因导致的,在运行时,会让调用的程序强制停止。
RuntimeException是那些可能在虚拟机正常运行期间抛出的异常的超类,无需进行声明。
- 自定义异常时,要么继承Exception,要么继承RuntimeException。
- throws使用在函数上,抛出的是异常类,可以抛出多个,用逗号隔开
- throw使用在函数内,抛出的是异常对象
- 处理完异常后的函数出栈,不再执行后续内容
异常捕捉
异常处理的捕捉形式,可以对异常进行针对性处理的方式。
具体格式:try{需要被检测异常的代码}catch(异常类 变量){处理异常的代码}finally{一定会被执行的代码}
class ExceptionDemo
{
public static void main(String[] args)
{
int[] arr new int[3];
Demo d = new Demo();
try{
int num = d.method(arr,-3);
//int num = d.method(arr,1);输出结果为:num=1 over
System.out.println("num="+num);}
catch (FuShuIndexException e)
{
System.out.println("角标异常");
e.printStackTrace();//即jvm默认的异常处理机制
}
catch (NullPointerException e)
{
System.out.println(e.toString());
}
System.out.println("over");
}//结果为:角标异常 异常信息 over
}
一个try可以对应多个catch,catch按先后顺序处理,即若第一个catch能够解决问题,后面的catch不再运行。所以父类的catch要放在最下面。
异常处理原则:
- 函数内容如果抛出需要检测的异常,那么函数上必须要声明,要么在函数内用try catch捕捉,否则编译失败。
- 如果调用了声明异常的函数,要么try catch要么throws,否则编译失败。
- 功能内容可以解决时用catch,解决不了时用throws告诉调用者
- 一个功能如果跑出了多个异常,调用时必须有对应个数的catch进行针对性处理,内部有几个需要检测的异常,就抛几个异常,抛出几个,就catch几个。
finally代码
通常用于关闭(释放)资源
三种情况:
- try catch finally
- try catch(多个)没有资源需要释放时,不用定义finally
- try finally 把异常留给别人处理(无法catch,只能throws),自己负责管理资源开启和关闭
应用
见exceptiontest.java文件
注意:子类覆盖父类只能抛出父类的异常或者其子类或者子集;如果父类的方法没有抛出异常,那么子类覆盖时绝对不能抛(如果有异常只能try)。
包
package mypack;//包的名称写在第一行
package mypack.A.B.C//会建立多层文件夹
class A
{
main(){}
}//编译方式变为:javac -d . A.java 会生成一个命名为mypack的文件夹
//运行方式变为:java mypack.A
不同包之间如何访问?
- 在同一目录下,包A要访问包B的class时使用: 包B的包名.类名。
- 不同目录的包之间访问,要先设置classpath。
- 在包文件下,没有加public的类其实就被封装了,不用private,加了public后,类名要和源文件名一致。
- 类中的方法也要加public。
- 将类的public换成protected时,只有其他包的子类才能调用该包父类的功能
packagedemo.java
package mypack;
class PackageDemo
{
public static void main(String[] args)
{
packa.DemoA d = new packa.DemoA();
d.show();
System.out.println("Hello Package");
}
}
DemoA.java
package packa;
public class DemoA
{
public void show()
{
System.out.println("demoa show run");
}
}
包中类的导入:import packa.DemoA
import packa.* 导入packa中的所有类
jar包:用于多个包的压缩