Java的Object类,接口
Object类
1. Object类概述
* Object 类是Java语言中的根类,即所有类的父类。它中描述的所有方法子类都可以使用。在对象实例化的时候,最终找的父类就是Object。如果一个类没有特别指定父类, 那么默认则继承自Object类。<!--more-->
2. toString方法
* 返回该对象的字符串表示,(类全名+@+hashcode)
* 想打印自己写的类的全部信息,需要重写toString方法(来自Object类的toString方法)
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
'}';
}
3. equals方法
* 指示其他某个对象是否与此对象“相等”。调用成员方法equals并指定参数为另一个对象,则可以判断这两个对象是否是相同的。这里的“相同”有默认和自定义两种方式。默认地址比较:如果没有覆盖重写equals方法,那么Object类中默认进行 == 运算符的对象地址比较,只要不是同一个对象,结果必然为false。自定义对象内容比较:如果希望进行对象的内容比较,即所有或指定的部分成员变量相同就判定两个对象相同,则可以覆盖重写equals方法。
* 两个变量相等分为两种相等,物理相等和逻辑相等
* 物理相等,即值相等,逻辑相等,即两个变量的地址相等,因此如果逻辑相等,那么一定物理相等,反之则不一定。
* 图片在下面
* 物理相等:“==” 逻辑相等:“equals()”,当不重写equals方法时,,equals与==无区别
* equals重写要点:
1. 物理相等的对象 一定要逻辑相等
2. 任何对象和null判断equals都返回false;
3. 类型不同的对象 直接返回false;
4. 强转参数类型后,比较需要的元素/要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
import java.util.Objects;
public class Person {
private String name;
private int age;
@Override
public boolean equals(Object o) {
// 如果对象地址一样,则认为相同
if (this == o)
return true;
// 如果参数为空,或者类型信息不一样,则认为不同
if (o == null || getClass() != o.getClass())
return false;
// 转换为当前类型
Person person = (Person) o;
// 要求基本类型相等,并且将引用类型交给java.util.Objects类的equals静态方法取用结果
return age == person.age && Objects.equals(name, person.name);
}
}
public boolean equals(Object obj) {
if(this==obj){
return true;
}
if(obj==null){
return false;
}
if(this.getClass() != obj.getClass()){
return false;
}
Teacher t = (Teacher) obj;
if(this.getTeacherNo() == t.getTeacherNo()){
return true;
}else{
return false;
}
4. hashCode方法
* hashcode就是jdk给每个对象的“身份证”,很大程度上可以体现内存地址。
* 返回该对象的哈希码值。
* 该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
* 一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
* 如果重写equals方法,不重写hashcode的时候,当我们使用HashSet,HashMap等哈希容器时就会出问题。
自己动手写equals,hashcode
@Override
public int hashCode() {
return this.getTeacherNo()^31+31;
}
5. finalize()方法
* 对象被回收之前要做的事。
* finalize被重写才能用
* 在日常很少使用,在main中以System.gc进行垃圾回收处理
6. 参数传递
* 要理解java的参数传递
public class Demo {
public static void main(String[] args) {
int a = 10;
A b = new A(10);
change1(a);
System.out.println(a);
change2(b);
System.out.println(b.a);
}
public static void change1(int a){
a=a+1;
}
public static void change2(A aa){
aa.a=aa.a+1;
}
}
运行结果:10 11
main方法和 change1,change2方法都在栈里,然而A对象以及它的实例在堆里,change1调用之后就直接出栈了,没有对main中的a进行改变,而change2方法将对象中的a值改变了 然后将对象中的a打印出 发现值确实被修改了
7. clone()方法
- 实现对象的浅克隆。
public class ObjectDemo implements Cloneable {//标志性接口
//只能给你看,不能改
int a ;
ObjectDemo objectDemo;
public ObjectDemo(int a) {
this.a = a;
}
public Object clone(){
Object cloneObject = null;
try {
cloneObject = super.clone();// 默认就是一级浅克隆
} catch (Exception e) {
e.printStackTrace();
}
return cloneObject;
}
@Override
public String toString() {
return "ObjectDemo{" +
"a=" + a +
'}';
}
}
MainClone.java:
public class MainClone {
public static void main(String[] args) {
// 演示对象的克隆
ObjectDemo o1 = new ObjectDemo(88);
o1.toString();
Object o = o1.clone();
System.out.println(o);
}
}
- clone是一个protected的方法,如果想要使用必须在类的内部定义,就好比你小时候想要零花钱,爸妈不给你但是你找你哥哥让他要了零花钱分你一些,你就可以使用零花钱啦
- 需要自己重写clone方法。
public Object clone(){
Object cloneObject = null;
try {
cloneObject = super.clone();// 默认就是一级浅克隆
} catch (Exception e) {
e.printStackTrace();
}
return cloneObject;
}
- 由于java类中可以调用别的类,所以类是不止一级的,但是java默认只支持一级浅克隆,所以java中很少使用clone方法。
抽象类
- 普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。
那么什么叫抽象方法呢?在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰。
拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。
- 定义一个抽象类
abstract class A{//定义一个抽象类
public void fun(){//普通方法
System.out.println("存在方法体的方法");
}
public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰
}
- 抽象类的特点:
- 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法);
- 抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
- 抽象类要使用必须依靠子类,使用extends继承,一个子类只能继承一个抽象类;
- 一个类继承了抽象类,则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);
- 抽象类不能用final声明,抽象方法也不能.
接口
- 概念
官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。通俗解释:接口可以理解为一种特殊的抽象类,里面全部是由全局常量和公共的抽象方法所组成。接口是解决Java无法使用多继承的一种手段,但是接口在实际中更多的作用是制定标准的。或者我们可以直接把接口理解为100%的抽象类,既接口中的方法必须全部是抽象方法。 - 定义一个接口
public interface Door {
void open();
void close();
}
class A implements Door{
@Override
public void open() {
System.out.println("具体实现open");
}
@Override
public void close() {
System.out.println("具体实现close");
}
}
- 接口的特点
- 接口不能被实例化;
- 接口中的成员方法默认修饰为public abstract,成员变量默认修饰为public static final;
- 接口没有构造方法;
- 一个类可以实现多个接口,格式如: class A implements B,C{ }
- 接口不能用final声明.
类与接口的区别
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static final变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多继承。
- 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
- 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
- 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
- 一个类只能继承一个抽象类,而一个类却可以实现多个接口。
- 接口体现一种规范,规范:一般都是一些功能的集合
类,接口,抽象类的总结
思想(关键)
1. 类、抽象类、接口都是类
a. 类是完全具体(不能包含抽象成分)
b. 抽象类是半抽象半具体
c. 完全抽象的(不能包含具体的方法)
2.抽象类一般体现一种共性,天生就被继承
3.接口体现一种规范,代表一些能力的集合。
语法
a. 抽象类用abstract修饰,只能单继承
b.抽象类中的方法必须加 abstract 修饰符,访问权限不能是 private
c. 接口的方法默认是就是 public,可以省略 abstract 关键字
d. 接口只能声明常量,接口中的成员变量没人就是 public staic final …..
e. 接口之间允许多继承
普通类 完全具体
抽象类 半抽象半具体
接口 完全抽象
接口 就好比 指定了 水果 有可以被吃的方法
实现接口 就好比 指定了某一种水果,通过被剥皮/直接吃的方式 被吃