第五章 面向对象编程 中
1.重写Override/Overwrite
1.1 方法的重写
- 发生在两个有继承关系的类中,且发生在子类里边(子类认为父类的方法不适用在子类里边,对父类的方法进行重写)
- 子类重写的方法的权限修饰符要大于等于父类中方法的权限修饰符
- 重写方法的返回类型在JDk5.0以前需要一模一样,在JDK5.0以后支持斜变类型
即支持返回其父类的子类类型
- 子类的异常处理部分要小于等于父类的异常类型
- @Override注解,表示下边被注解的方法必须要重写父类的某个方法
1.2 方法的重载
方法重载的条件
- 必须发生在同一个类体
- 方法名需要完全相同
- 方法的参数需要不同
- 参数类型不同
- 参数个数不同
- 参数顺序不同
方法重载对返回值类型和修饰符没有要求
方法重载的作用是为了满足用户的不同需求
区分方法的重写和重载
- 二者的概念:
- 重写和重载的具体规则
- 重载:不表现为多态性
重写表现为多态性
2. super的使用
- super理解为父类的,可用来调用属性,方法,构造器
- super的使用
- 在子类的方法或构造器中,通过使用super.属性/super.方法的方式,显式的调用父类中声明的属性或方法,通常情况下省略super.
- 特殊的:当子类的父类定义同名的属性时,要想在子类中调用父类的属性,必须显式的使用super调用
- super调用构造器
- 在子类的构造器中显示的使用“super(形参列表)”的方式,调用父类中声明的指定的构造器
- super(形参列表)的使用,必须声明在子类构造器的首行
- 在类的构造器中,针对于this(形参列表)或super(形参列表)只能二选一,不能同时出现
- 在构造器的首行,没有限时的声明this(形参列表)或super(形参列表),则默认的是父类中空参的构造器
- 在类的多个构造器中,至少有一个类的构造器中会用了super(形参列表),调用父类的构造器
3.子类对象实例化过程
- 从结果来看
子类继承父类以后,就获取了父类中声明的属性或方法
创建子类的对象,在堆空间,就会加载所有父类中声明的属性 - 从过程来看
通过子类的构造器创建子类对象时,一定会间接或直接的调用其父类的构造器,进而调用父类的父类的构造器,,直接调用了java.lang.Object类的空参构造器为止,因为家在所有父类的结构,所以才可以看到内存中有父类的结构,子类对象才可以考虑进行调用
4. OOP特征三:多态性
- 多态性可以理解为一个事物的多种形态
- 对象的多态性,父类的引用指向子类的的对象
Person p1 = new Women();
Person p2 = new Men();
- 多态的使用:虚拟方法调用
有了对象的多态性以后,在编译时,只能调用父类中声明的方法,但是在运行期间,实际执行的是子类重写父类的方法,
编译看左边,执行看右边 - 多态是运行时行为
5. Object类的使用
- .Object是所有类的父类
5.1 clone()的使用
- 将Object类的克隆方法权限改大变成public的,然后用super.clone()调用父类的克隆方法,强转成要返回的类型
- 将要实现克隆方法的类实现允许克隆的接口**(implements Cloneable)**
- 在main()方法中调用,并抛出异常
public class Exec1 {
public static void main(String[] args)throws Exception{
OS android = new OS("安卓");
OS flyme = android.clone();
= "魅族";
System.out.println(android == flyme);
}
}
class OS implements Cloneable{
String name;
public OS(String name){
= name;
}
@Override
public OS clone() throws CloneNotSupportedException{
return (OS)(super.clone());
}
}
5.2 finalize()
对象的遗言方法,当一个对象要被gc()回收掉的时候回主动执行的一个方法
面试题
final 和 **finalize()**的区别
雷锋和雷锋塔的区别,final是一个修饰符,表示最终的可以用来修饰类,方法,变量
finali是Object类型里边的一个方法,当对象要被回收的时候会主动执行的一个方法
5.3 toString()
- 重写toString()方法。打印自己想要的信息
public class TestToString2{
public static void main(String[] args){
Person p1 = new Person("黄晓明",35,'男');
Person p2 = new Person("baby",28,'女');
System.out.println(p1);
System.out.println(p2);
}
}
class Person{
String name;
int age;
char sex;
public Person(String name,int age,char sex){
= name;
this.age = age;
this.sex = sex;
}
@Override
public String toString(){
return name + (sex == '男' ? "\t先生" : "\t女士") + age + "岁";
}
}
5.4 equals()
重写equals()方法
public class ExecEquals1{
public static void main(String[] args){
Food f1 = new Food("猪耳朵拌黄瓜",23,"凉菜");
Food f2 = new Food("猪耳朵拌黄瓜",25,"凉菜");
System.out.println(f1.equals(f2));
}
}
class Food{
String name;
double price;
String type;
public Food(String name,double price,String type){
= name;
this.price = price;
this.type = type;
}
@Override
public boolean equals(Object obj){
if(this == obj) return true;
if(obj == null) return false;
if(obj instanceof Food){
Food food = (Food) obj;
return .equals() && this.type.equals(food.type);
}
return false;
}
}
5.5.hashCode()
- 得到一个对象的散列
将一大组数据分散成不同的小组
特征码 - 当equals()方法被重写以后,通常也需要重写hashCode()方法,以便维护hashCode()方法的通用规范,该方法规定相等的对象应该有相等的哈希值
6.包装类的使用
服务于集合
基本数据类型 |
包装类 |
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
boolean |
Boolean |
char |
Character(不存在parse方法) |
- java提供了八种基本数据类型对应的包装类,使得基本数据类型的变量具有了类的特征。
6.1 基本数据类型,包装类,String的相互转换
public class WrapperTest{
public static void main(String[] args){
}
@Test
public void test1(){
}
//自动装箱 基本数据类型 --> 包装类
int num1 = 10 ;
Integer in1 = num1;
//自动拆箱 包装类 --> 基本数据类型
int num2 = in1;
//基本数据类型,包装类 --->String类型
int num = 10;
//方式一 连接运算
String str1 = num + "";
//方式二 :调用String的valueOf(Xxx xxx)
float f1 = 1.3;
String str2 = String.valueOf(f1);
//String --> 基本数据类型,包装类
String str3 = "123";
int num4 = Integer.paserInt(str3);
}
例题
Object obj1 = true ? new Integer(1) : new Double(2.0);
System.out.println(ojb1);
//结果为1.0
//三元运算符运算式要保证两个结果类型一致。所以会对Integer类型的进行自动类型提升 变为Double型
//***************************
Object obj2;
if(true)
obj2 = new Inetger(1);
else
obj2 = new Double(2.0);
System.out.println(ojb2);
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println( i == j);//false
//Integer内部定义了IntegerCache的结构,在其中定义了Integer[]
//保存了-128~127范围的整数,如果用自动装箱的方式,给Integer固执的范围在这个范围内,可以直接使用数组的元素,不用new了,提高了效率
Integer m = 1;
Integer n = 1;
System.out.println( m == n);//false
Integer i = 128;
Integer j = 128;
System.out.println( x == y);//false