由于继承中有一个现象:方法重写。
所以父类的功能,就会被子类给覆盖掉。
有些时候,我们不想让子类去覆盖掉父类的功能,只能让他使用。
针对这种情况,Java提供了一个关键字:final
final:最终的意思。它可以修饰类,方法,变量。
一.
final特点:
final 可以修饰类,该类不能被继承。
final 可以修饰方法,该方法不能被重写。
final 可以修饰变量,变量就变成了常量,只能被赋值一次。
final 修饰局部变量问题
基本类型:值不能改变。
引用类型:地址值不能被改变。
final 修饰变量的初始化时机
1.被final修饰的变量只能赋值一次
2.在构造方法完毕前。(非静态的常量)
二.
重写ToString()方法
Object的toString()方法帮助我们返回一个字符串,这个字符串的格式是固定的:类名@hashcode。
作用:返回该对象的字符串表示,默认情况下的数据对我们来说没有意义,一般建议重写该方法。
代码
package com.atguigu.day10; public class Person { private String name; private int age; private double height; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public Person(String name, int age, double height) { this.name = name; this.age = age; this.height = height; } @Override public String toString(){ return "name:"+name+" age:"+age+" height:"+height; } }
main
package com.atguigu.day10; public class Test { public static void main(String args[]) { Person p1 = new Person("lin1",23,1.80); System.out.println(p1.toString()); } }
输出
name:lin1 age:23 height:1.8
三.getClass
getClass:获取运行时类型
package com.atguigu.day10; public class Person { private String name; private int age; private double height; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public Person(String name, int age, double height) { this.name = name; this.age = age; this.height = height; } @Override public String toString(){ return "name:"+name+" age:"+age+" height:"+height; } public void eat(){ System.out.println("just eating"); } } class Student extends Person{ public Student(String name, int age, double height) { super(name, age, height); } @Override public void eat() { System.out.println("student eat"); } }
main
package com.atguigu.day10; public class Test { public static void main(String args[]) { Person p1 = new Person("lin1",23,1.80); System.out.println(p1.toString()); Person p2 = new Student("lin2",19,1.80); Class class1 = p2.getClass(); System.out.println(class1); } }
输出:
name:lin1 age:23 height:1.8
class com.atguigu.day10.Student
四.finalize
垃圾回收机器(Garbage Collection),也叫GC,垃圾回收器主要有一下特点:
当对象不再被程序所使用的时候,垃圾回收器将会将其回收
垃圾回收是在后台运行的,我们无法命令垃圾回收器马上回收资源,但是我们可以告诉他可以尽快回收资源(System.gc()和Runtime.getRuntime().gc())
垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize()方法
GC主要针对堆内存
单例模式的缺点
finalize()是Object里面的一个方法,当一个堆空间中的对象没有被栈空间变量指向的时候,这个对象会等待被java回收:jdk里面是这样实现的:
protected void finalize() throws Throwable { } }
代码:
public class testFinalize { public static void main(String[] args){ Person p = new Person(); p = null;//此时堆当中的Person对象就没有变量指向了,就变成了垃圾,等到垃圾回收机制调用的finalize()的时候会输出 } } class Person { protected void finalize() throws Throwable{ System.out.println("回收了!!!"); } }
执行后,垃圾回收机制都没有启动,可以适当建议启动
public class testFinalize { public static void main(String[] args){ Person p = new Person(); p = null; System.gc(); } } class Person { protected void finalize() throws Throwable{ System.out.println("回收了!!!"); } }
依然不好使
public class testFinalize { public static void main(String[] args){ Person p = new Person(); for(int i = 0 ; i< 1000; i++){ p = null; } System.gc();//增加垃圾回收器启动的概率 } } class Person { protected void finalize() throws Throwable{ System.out.println("回收了!!!"); } }
输出:
回收了!!!
hashcode
public class HashCode { /* hashCode:用于返回当前对象的hash码 如果两个对象的hash值是不同的,那么这两个对象一定不相等 如果两个对象的hash值是相同的,那么这两个对象不一定相等 由于不同的对象可能产生hash码可能一样,所以重写让不同对象的hash码不同 */ public static void main(String[] args) { Person p1 = new Person("lin1",23,1.80); int hcode = p1.hashCode(); System.out.println(hcode); //输出460141958 } }
五.equals()
==和equals()在object类默认是都是比较地址值
==:比较基本数据类型,比较的是实际的值,比较引用数据类型,比较的是地址值
equals:重写前比较的是地址值,重写后比较属性值
作用:用于比较两个对象是否相同
注意:重写equals时第一件事就是判断给定的对象是否和当前对象为同一类型。不是同一类型直接返回false,不具有可比性。
equals比较前需要进行安全验证,确保给定的对象不是null,obj若是null,说明该引用变量没有指向任何对象,那么就不能引用obj所指向对象(因为对象不存在)的属性或方法,若这么做会引发NullPointerException,空指针异常!
代码:
package com.atguigu.day10; public class Demo3 { public static void main(String[] args) { Student1 s1=new Student1("lin1",18); Student1 s2=new Student1("lin1",18); Student1 s3=new Student1("lin2",18); System.out.println("s1.equals(s2)"+s1.equals(s2)); System.out.println("s1.equals(s3)"+s1.equals(s3)); } } class Student1{ String name; int age; public Student1(String name,int age){ this.name=name; this.age=age; } @Override public boolean equals(Object obj){ if(this==obj){ return true; } if(!(obj instanceof Student1)){ return false; } Student1 objStudent=(Student1)obj; if(this.name.equals(objStudent.name) && this.age==objStudent.age){ return true; } return false; } }
如果不重写equals,则输出结果都是false,重写后第一个是true,第二个是false
另外:因为浮点数存储的是约数,不建议使用==比较浮点类型