一、Object
1、概述:
Object是所有类的超类,父类。所有的类都直接或在间接继承自Object。
2、Object类中的常用方法
------equals(Object obj)、toString()、getClass()、hashCode()
A:public boolean equals(Ojbect obj)
**对对象进行比较,该方法默认比较的是对象的地址。而自定义的对象,比较地址没有什么意义。所有呢,我们自定义的对象,一般都会重写此方法,完成自己想要比较的内容。
class Student
{
private String name;
private int age;
Student(){}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
//重写equals满足:同名和同年龄的学生是同一个对象。
public boolean equals(Object obj) {//Object obj = new Student();
//为了提高效率
if(this == obj){
return true;
}
//为了程序的健壮性
if(!(obj instanceof Student)){
return false;//实际开发会抛出一个异常而不return false
}
Student s = (Student)obj;
if(this.age == s.age && this.name.equals(s.name)){
return true;
}else{
return false;
}
}
}
class ObjectDemo{
public static void main(String[] args){
Student s1 = new Student();
s1.setName("林青霞");
s1.setAge(20);
Student s2 = new Student();
s2.setName("林青霞");
s2.setAge(20);
System.out.println(s1.equals(s2));//true;
Teacher t = new Teacher();
System.out.println(s1.equals(t));
System.out.println(s1.equals(s1));
}
}
B:public String toString()
**将对象按照字符串的格式输出。输出格式:对象类型@对象的哈希值
一般来说,这个值对我们没有任何意义。所以我们会重写此方法。建立自己特有的 字符串表示。
C:public final Class<?> getClass()
**获取的是对象的字节码文件 反射
D:public int hashCode()
**返回该对象的哈希码值。(十进制的)
3、注意事项
-------------------- "=="和equals方法究竟有什么区别?
(单独把一个东西说清楚,然后再说清楚另一个,这样,它们的区别自然就出来了,混在一起说,则很难说清楚)
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
自学Math类。完成如下作业:
1:给一个圆,把半径做为属性,求圆的面积。要求使用Math类中一些内容。
import java.util.*;
class AreaTest{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
double a = sc.nextDouble();
final double B =2;
GetArea ga = new GetArea();
System.out.println("半径为"+a+"的圆的面积是:"+ga.getArea(a,B));
}
}
class GetArea{
public double getArea(double a,double b){
double s = Math.PI*Math.pow(a,b);
return s;
}
}
二、内部类
1、概述
-----在类的内部定义的类,只不过是类的位置发生了变化而已。
2、特点
A:内部类可以直接访问外部类的成员,包括private修饰的。
内部类都持有一个外部类的引用-------外部类名.this
B:外部类要想访问内部类,必须创建对象。
3、在类中的所在位置
A:成员位置
class Outer{
private int num = 10;
class Inner(){
void show(){
System.out.println("show");
}
}
void method(){
Inner i = new Inner();
i.show();
}
}
外部:访问权限不为private
|
**它可以被private修饰
class Body{
private class Heart{
//code
}
public Heart getHeart(){
//code
return new Heart();
}
}
**它可以被static修饰,它只能访问外部类中的静态成员
(内部类没有外部类的引用)
如果内部类中定义了静态成员,那么内部类必须定义为静态的。
|
B:局部位置
class Outer{
void method(){
final int X = 10;
class Inner{
void show(){
System.out.println(X);
}
}
Inner i = new Inner();
i.show();
}
}
**它可以访问外部类的成员,也可以访问局部变量,但是访问局部的变量必须
被final修饰,其实也就是常量。<不定义为final,此变量会随着方法的结 束而释放,此时,内部类的引用可能还存在(用父类Object进行接收),此时 无法访问该变量>
**它不可以被private或者static修饰。
4、匿名内部类
A:没有名字的局部的内部类。
B:前提
**内部类可以继承或实现一个外部类或者接口。
C:格式
**new 外部类名或者接口名(){覆盖类或者接口中的代码,(也可以自定义内容。)}
D:简单理解:
**就是建立一个带内容的外部类或者接口的子类匿名对象。
举例:
interface Inter{
public abstract void show();
}
class Outer{
void method(){
//第一种:
new Inter(){
public void show(){
System.out.println("show");
}
}.show();
//第二种:调用多个方法的时候可以采用这种
Inter i = new Inter(){
public void show(){
System.out.println("show");
}
};
i.show();
}
}
5、什么时候使用匿名内部类?
通常在使用方法是接口类型参数,并该接口中的方法不超过三个时,可以将匿名内部类作为参数传递。
面试题:自己再分析一次。
interface Inter{
void show();
}
class Outer{
//请补足代码。
static Inter method(){
/*
class Demo implements Inter{
public void show(){
System.out.println("show");
}
}
*/
//Inter i = new Demo();
return new Inter(){
public void show(){
System.out.println("show");
}
};
}
}
class InnerClassTest{
Outer.method().show();
}
三、异常
1、概述
程序有可能出现问题,我们把出现的问题就称为异常.
2、主函数处理异常的方式
A:主函数手动处理方式的方式.(异常处理机制)
B:采用的是jvm的默认处理机制.
把异常的信息打印输出到控制台.
3、异常的体系结构
A:Throwable 异常的超类
**Error
我们不可解决的问题。面对此种问题,我们无能为力。
比如说:类不存在或者内存溢出。
**Exception
在运行时运行出现的一些不正常的状况,这个状况我们通过修改代码,是可以解决的。
举例:骑自行车回家。
走不好的路,车爆胎,是异常。
发洪水,路给冲断了,是错误。
2003年,非典。这个东西来了,是错误。
头疼,感冒了。是异常。
B:通过分析,发现我们要学习异常。
4、异常的处理方式
A:try...catch...finally
**基本格式
try{
//有可能出现异常的代码
}catch(异常类 名字){
//处理异常的代码
}finally{
//一定会被执行的代码,如释放资源
}
**变形格式
try...catch
try...catch...catch...catch...
try...finally
try...catch...finally
try...catch...catch...finally
**finally的特点
它永远都会被执行.
有一个特殊情况:如果在代码中jvm退出系统而来,那么finally就不会被执行.
**面试题
***final,finally,finalize区别?
final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。 内部类要访问局部变量,局部变量必须定义成final类型,例如,一段代码……
finally是异常处理语句结构的一部分,表示总是执行。
finalize是Object类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源回收,例如关闭文件等。JVM不保证此方法总被调用
***
try{
System.out.println("aaa");
System.out.println(10/0);//ArithmeticException
}catch(Exception e){
System.out.println("bbb");
return;
}finally{
System.out.println("ccc");
}
请问这个程序运行结果?
aaa
bbb
ccc
B:throws,throw 抛出
区别:------一旦执行throw语句,就结束功能!
**使用位置
throws在方法的声明上使用
throw在方法体内使用
**使用格式
throws后面跟的使用异常的类名
throw后面跟的是对象.格式:throw new 异常类名(参数);
**联系
有throws不一定有throw
有throw一定有throws
C:两种处理方式用哪种呢?<何时使用try,何时使用throw呢?>
**自己能够处理的就自己处理.
**自己实在处理不了的交给调用者.
5、Exception的分类
A:Exception
这种类型的异常,如果抛出,在编译的时候就会检查.此类异常需要编写针对性的处 理代码进行处理。
B:RuntimeException
这种类型的异常,如果抛出,在编译的时候不检查,运行的时候直接处理.
这种异常必须通过修改代码才能解决.所以,一般针对这种异常,我们不处理,jvm处 理。
6、自定义异常
除数不能为负数.
1:继承自Exception或者RuntimeException.必须的!
2:在自定义异常里面,提供一个带参构造
class MyException extends Exception{
MyException(){}
MyExcepiton(String message){
super(message);
}
}
class Demo{
int div(int a,int b)throws RuntimeException{
if(b<0){
throw new MyException("除数不能为负数!");
}
}
}
7、异常使用细节
A:我们为什么要使用try…catch语句进行异常处理呢?只有在某个功能上可能出现某种隐患,并且在该功能的声明上进行了描述时,我们才能够使用此种针对性的处理方式。
B:如果一个功能抛出多个异常,那么在调用该功能时,需要有多个catch进行每一个异常的针对性处理,如果多个catch中有父类异常,一定要定义在最下面,否则编译失败。
C:函数内抛出异常,函数上一定要使用thows进行标识,调用者如果调用了该函数,就需要对其进行处理(try或者抛出),否则编译失败。