面对对象4【抽象abstract】【接口interface】【多态】【instanceof关键字】【Object类】
2014-09-05 22:48
771 查看
一、抽象类(AbstractClass)
1、抽象:就是从多个事物中将共性的,本质的内容抽取出来。简单说:就是看不懂的、模糊的、不具体的事物。
2、抽象类:表示具体功能不明确的,被abstract关键字修饰,且包含抽象方法的类。
3、抽象方法:只有功能声明,没有功能主体的方法称为抽象方法。
4、抽象类的特点:
①、抽象方法一定要定义在抽象类中。
②、抽象方法和抽象类都必须被abstract关键字修饰。
③、抽象类不可以用new创建对象。因为调用抽象方法没意义。
④、抽象类中的抽象方法要被使用,必须由子类覆写其所有的抽象方法后,建立子类对象调用。
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。
5、抽象类、抽象方法的定义格式:
abstract class 抽象类名
{
访问权限 abstract 返回值类型 方法名称(参数);
}
6、抽象类和一般类的区别:
①.抽象类比一般类多了抽象函数。就是在类中可以定义抽象方法。
②.抽象类不可以被实例化。
特殊:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
7、注意:在使用abstract关键字修饰抽象方法时不能使用private修饰。因为抽象方法必须要被子类覆写,而如果使用了private修饰,则子类是无法覆写的。
代码示例:
abstract class Student{ abstract void study(); //抽象方法。 } class BaseStudent extends Student{ void study(){ System.out.println("base study"); //覆写抽象方法。 } } class AdvStudent extends Student{ void study(){ System.out.println("adv study"); //覆写抽象方法。 } } class AbstractDemo { public static void main(String[] args) { newBaseStudent().study(); //创建子类匿名对象并调用覆写后的方法。 } }
二、接口(interface)
1、接口:一种特殊的抽象类,由全局常量和公共的抽象方法组成。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
2、接口的定义格式:用interface关键字来定义
interface
接口名称
{
public static final返回值类型常量名 =初始化值; //全局常量
public abstract返回值类型抽象方法名(); //公共抽象方法
}
代码示例:
interface Inter { public static final int NUM = 3; public abstract void show(); }
3、接口在定义时的格式特点:
①、接口中常见定义:常量、抽象方法。
②、接口中的成员都有固定修饰符。
常量:public static final
方法:public abstract
4、接口的注意事项:
①、接口中的成员都是public权限的,绝对不可以改变。
②、接口中全局常量前面的public static final和抽象方法前面的public abstract都是可以省略掉的,即使不写,系统默认也会给它加上。
③、接口不可以被创建对象,因为有抽象方法。
④、需要被子类实现,子类将接口中的抽象方法全都覆盖后,子类才可以实例化。
否则子类是一个抽象类。
⑤、接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。
5、接口之间的关系
类和类之间是继承关系 —— extends
类和接口之间是实现关系 —— implements
接口和接口之间是继承关系。
示例代码:
interface A{ void methodA(); } interface Bextends A{ void methodB(); } interface Cextends B{ void methodC(); } class Dimplements C{ pubilc void methodA(){} pubilc void methodB(){} pubilc void methodC(){} }
注意:接口和接口之间支持多继承。因为接口里面都是抽象方法。
示例代码:
interface A{ void methodA(); } interface B{ void methodB(); } interface Cextends B,A{ void methodC(); }
6、接口的特点(和好处):
接口是对外暴露的规则。
接口是程序的功能扩展。
接口的出现降低耦合性(即:降低紧密联系程度)。
接口可以用来多实现。
类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
接口与接口之间可以有继承关系。
7、接口与抽象类的区别:
共性 | 都是不断抽取出来的抽象的概念 |
区别1 | 抽象类体现继承关系,一个类只能单继承 接口体现实现关系,一个类可以多实现 |
区别2 | 抽象类是继承,是 "is a "关系 接口是实现,是 "like a"关系 |
区别3 | 抽象类中可以定义非抽象方法,供子类直接使用 接口的方法都是抽象,接口中的成员都有固定修饰符 |
三、多态
1、多态:可以理解为事物存在的体现形态。例如:人→ 男人、女人
动物 → 猫、狗
创建一个猫的对象可以通过以下两种方式:
猫 x = new 猫();
动物 x = new 猫();
2、多态的体现:
父类的引用指向了自己的子类对象。
//动物 x= new
猫();
父类的引用也可以接收自己的子类对象。(将父类的引用做为函数的参数进行传递)
3、多态的前提:
必须是类与类之间有关系。要么继承,要么实现。
通常还有一个前提:存在覆盖。
4、多态的好处:多态的出现大大的提高了程序的扩展性。
5、多态的弊端:提高了扩展性,但是只能使用父类的引用访问父类中的成员。
6、多态转型:
Java中多态性的体现形式主要有两种:
①、方法的重载和覆写
②、对象的多态性
对象的多态性主要分为两种类型:
向上转型:子类对象→父类对象。用子类去实例化父类对象,程序会自动完成。
向下转型:父类对象→子类对象。强制将父类的引用转成子类类型。
对象转型格式:
向上转型:父类父类对象 =子类实例;
//例如:Animal a = newCat();
向下转型:子类子类实例 = (子类)父类对象; //例如:Cat
c =(Cat)a;
注意:千万不要出现将父类对象转成子类类型的操作。
示例代码:
Animal a = newAnimal();
Cat c = (Cat)a;
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被前者转换。
总结一句话:多态自始至终都是子类对象在做着变化。
注意:在进行对象的向下转型前,必须首先发生对象的向上转型,否则将会出现对象类型转换异常。
示例代码:
abstract class Animal{ public abstract void eat(); //动物共有的行为方法。 } class Cat extends Animal{ public void eat(){ System.out.println("吃鱼"); } public void catchMouse(){ //猫特有的行为方法。 System.out.println("抓老鼠"); } } class Dog extends Animal{ public void eat(){ System.out.println("吃骨头"); } public void kanJia(){ //狗特有的行为方法。 System.out.println("看家"); } } class DuoTaiDemo2{ public static void main(String[] args) { Animal a = new Animal(); Cat c = (Cat)a; //报错。会出现类型转换异常。 /* 正确的方式: Animal a = new Cat(); Cat c = (Cat)a; */ } }
报错原因:父类用其本身类实例化自己的对象,但它并不知道谁是自己的子类,在转换的时候肯定就会出现类型转换异常。
解决方式:只要将这两个对象建立好关系即可,即在声明父类对象时先发生向上转型,相当于是用子类去实例化父类对象,也就是说这个时候父类知道有这么一个子类。
7、多态中成员的特点:
①—1、多态中(非静态)成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过;如果没有则编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
示例代码:
class Fu{ void method1(){ System.out.println("fu method_1"); } void method2(){ System.out.println("fu method_2"); } } class Zi extends Fu{ void method1(){ System.out.println("zimethod_1"); } void method3(){ System.out.println("zimethod_3"); } } class DuoTaiDemo4 { public static void main(String[] args) { Fu f = new Zi(); f.method1(); //结果是zi method_1。打印的是被子类覆写之后的方法。 f.method2(); //f.method3(); //会报错,因为父类中没有method3这个方法。 } }
个人总结:当发生向上转型之后,用父类对象调用的方法一定是被子类覆写之后的方法。
为什么上面示例中f.method1();的结果是子类中的zi method_1呢?
因为一般方法存在于内存的方法区的非静态方法区,是通过对象或者this、super等调用,而当用子类实例化父类对象的时候,再用父类对象去调用子父类中的同名方法,则相当于是以【new子类().方法名();】的形式在调用,所以运行的结果是子类中同名方法的结果。
①—2、多态中静态成员函数的特点:
无论编译和运行,都参考左边。
示例代码:
class Fu{ static void method4(){ System.out.println("fumethod_4"); } } class Zi extends Fu{ static void method4(){ System.out.println("zimethod_4"); } } class DuoTaiDemo4 { public static void main(String[] args) { Fu f = new Zi(); f.method4(); //结果是:fumethod_4。开发中一般不会出现,几乎不会去覆盖静态。面试中有可能遇到。 Zi z = new Zi(); z.method4(); //结果是:zimethod_4 } }
为什么上面示例中f.method4();的结果是父类中的fu method_4呢?
因为当用子类去实例化父类对象的时候,JVM会将父类、子类都加载进内存,但是这个时候静态方法已经在内存中优先于对象存在了,也就是说这个时候需不需要对象都没什么特别的意义,父类对象调用的就是本类中的静态方法。
②、多态中成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
换句话说就是:当父类和子类中出现同名变量的时候,多态情况下看的是左边。
示例代码:
class Fu{ int num = 5; } class Zi extends Fu{ int num = 8; } class DuoTaiDemo4 { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num); //结果是:5 Zi z = new Zi(); System.out.println(z.num); //结果是:8 } }
四、instanceof关键字
1、作用:在Java中,可以用instanceof关键字判断一个对象到底是哪个类的实例。2、使用格式:
对象 instanceof类 ——> 返回值类型是boolean型
示例代码:
public static void function(Animal a) //将父类的引用做为函数的参数接收进来。 { a.eat(); if(a instanceof Cat) //判断传进来的对象是否是Cat类的对象。 { Cat c = (Cat)a; //如果是就执行向下转型操作。 c.catchMouse(); //执行Cat类对象的特有行为方法。 } else if(a instanceof Dog) { Dog d = (Dog)a; d.kanJia(); } }
五、Object类
1、Object类:是Java中所有类的直接或者间接的父类,位于Java继承体系的根节点。一个类如果没有明确的继承一个类,则它肯定是Object的子类。
该类中所具备的功能是所有对象都具备的。
2、Object类中只有一个无参数的构造方法,所有没有明确父类的类默认都隐式的调用了Object类的构造方法。
3、所有的对象都可以向Object进行转换,即一切的引用数据类型都可以使用Object进行接收。
4、Object类中的常用方法:
序号 | 方法名称 | 类型 | 描述 |
1 | public Object() | 构造 | 构造方法 |
2 | public boolean equals(Object obj) | 普通 | 对象比较 |
3 | public int hashCode() | 普通 | 取得哈希值 |
4 | public String toString() | 普通 | 对象打印时调用 |
代码示例:
class Demo {} class ObjectDemo{ public static void main(String[] args) { Demo d1 = new Demo(); Demo d2 = new Demo(); Demo d3 = d1; System.out.println(d1.equals(d3)); //结果是:true System.out.println(d1.equals(d2)); //结果是:false System.out.println(d1==d2); //结果是:false System.out.println(d1==d3); //结果是:true } }
其实equal()方法底层的比较原理就是使用的比较运算符“==”
注意:
Object类中已经提供了对对象是否相同的比较方式。如果自定义类中也有比较相同的功能,没有必要重新定义。
只要沿袭父类中的功能,建立自己特有的比较内容即可。这就是覆盖。
示例代码:
class Demo{ private int num; Demo(int num){ this.num= num; } public boolean equals(Object obj){ //在自定义类中覆写Object类中已经存在的比较方法以达到沿袭父类功能的效果。 if(!(obj instanceof Demo)) //加入判断来控制传入对象是否具有可比性。 return false; Demo d = (Demo)obj; //向下转型。 return this.num == d.num; } } class Person{} class ObjectDemo{ public static void main(String[] args) { Demo d1 = new Demo(4); Demo d2 = new Demo(4); Person p = new Person(); System.out.println(d1.equals(p)); //两种不同类型的对象比较。会报错。类型转换异常。 } }
toString()方法:将功能返回的结果以字符串形式返回。
Java中,对象输出时一定会调用Object类中的toString()方法,但是加与不加toString()的最终打印结果是一样的。
示例代码:
class Demo(){} class ObjectDemo { public static void main(String[] args) { Demo d1 = new Demo(); System.out.println(d1); //结果是:Demo@18b3364 System.out.println(d1.toString()); //结果是:Demo@18b3364 }
/*
Demo@18b3364:Demo表示对象所属类的名称,@后面的部分是该对象在内存中的哈希地址值。
*/
//对象的哈希地址值可以通过Object类中的hashCode()方法获取。由于hashCode()方法返回的默认是int类型的值,所以需要被转换成16进制的形式才能跟上面的结果中的哈希值部分一样。
Class c =d1.getClass();
//获取Demo类的类文件对象。
System.out.println(c.getName());
//输出获取到的类文件的类名。
//通过hashCode()方法获取Demo类对象的哈希值,并转成16进制表现形式。
System.out.println(c.getName()+"@"+Integer.toHexString(d1.hashCode()));
//输出结果是:Demo@18b3364
}
相关文章推荐
- 马士兵J2SE-第三章-面向对象-Object类:toString方法、equals方法、对象转型、抽象类抽象方法、final关键字、接口
- java 面对对象(抽象 继承 接口 多态)
- java之接口(interface)和抽象(abstract)关键字详解
- 浅谈java 面对对象(抽象 继承 接口 多态)
- 黑马程序员_面向对象2_(继承、多态、抽象类abstract、接口interface、内部类)
- NO8.java笔记【面向对象、抽象类、abstract、接口、interface、多态 、内部类、匿名内部类、异常、Object类】
- 2.0 面向对象 类与实例(关键字)、封装、继承、多态(虚方法,抽象类,抽象方法,接口)
- 面向对象多态的实现(抽象类Abstract和接口Interface的用法区别)
- 面向对象高级续2(instanceof关键字、抽象类和接口的应用、Object类、包装类)
- Java中 关键字final,抽象类abstract, 接口interface ,多态
- 黑马程序员_面向对象二(继承,多态,抽象类abstract,接口Interface,内部类)
- 面向对象的开发5 抽象关键字abstract
- 黑马程序员面试题面向对象二(多态,抽象类abstract,接口Interface,内部类,异常Exception,包package,String类,StringBuffer)
- 黑马程序员—java基础学习--抽象类(abstract)、接口(interface)、多态
- Java面向对象多态abstract关键字
- JAVA笔记6__抽象类/接口/多态/instanceof关键字、父类设计法则
- 第二周第二天(abstract;匿名内部类/单例设计模式/不用for循环求11000的值/finalstatic/interface 接口/instanceof;interface)
- 7月21日---关键字、抽象方法、抽象类、接口、多态及总结、设计模式
- OO-面对对象的特征--多态、抽象
- 【07】面对对象3_继承,super,函数覆盖,子类实例化,final,抽象,接口