面向对象三个特征:1、封转(private) 2、继承 3、多态
class Person { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public String talk() { return "My name is "+this.name+"\nMy age is "+age; } } class Student {//Student类中有很多代码和Person类中的重复了 private String name; private int age; private String school; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public void setSchool(String school) { this.school = school; } public String getName() { return this.name; } public int getAge() { return this.age; } public String getSchool() { return this.school; } public String talk() { return "My name is "+this.name+"\nMy age is "+age+"\nMy school is "+this.school; } } |
继承可以简化类中的代码,扩展类中的功能。格式:class 子类 extends 父类
class Person { private String name; private int age; public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public String talk() { return "My name is "+this.name+"\nMy age is "+age; } } class Student extends Person {//Student子类扩展了Person父类的功能省去了很多代码 Java中父类叫超类 private String school; public void setSchool(String school) { this.school = school; } public String getSchool() { return this.school; } public String talk() { //return "My name is "+this.name+"\nMy age is "+age+"\nMy school is "+this.school; return "My name is "+this.getName()+"\nMy age is "+this.getAge()+"\nMy school is "+this.school; //name、age在Person类中被封装了,继承父类时访问私有方法需要使用getter()方法获得 } } public class JavaDemo75 { public static void main(String arg[]) { Student s = new Student(); s.setName("Rock"); s.setAge(22); s.setSchool("24 school,East area,BJ City"); System.out.println(s.talk()); } } |
子类扩展了父类的功能,同时可以将父类中的操作全部继承下来。
Java只支持单继承,不支持多继承。
//Java只支持单继承,不支持多继承 class A//父类 { } class B//父类 { } class C extends A,B//C继承A父类、B父类语法错误 { } //Java中允许多层继承 class A//父类 { } class B extends A//子类 { } class C extends B//孙子类 { } |
一个子类只能有一个父类,一个父类可以有多个子类。
子类只继承父类所有的共有方法和属性。使用父类中的私有属性可以使用getter()方法调用。
class A { private String name ; public void setName(String name) { this.name = name ; } public String getName() { return this.name ; } }; class B extends A { public void say() { System.out.println(getName()) ; } }; |
子类对象实例化过程时:1、先调用父类构造方法2、在调用子类构造方法
class A { public A() { System.out.println("class A()"); } } class B extends A { public B() { //此处隐含代码 //super();调用父类无惨构造方法 System.out.println("class B()"); } } public class JavaDemo77 { public static void main(String args[]) {//子类对象实例化过程 B b = new B(); } } |
方法覆写:
1、方法名称完全一致,参数也要一直,在覆写之后子类调用的永远是覆写后的方法。
2、覆写时子类的访问权限不能比父类拥有更严格的权限,覆写后的权限最好与父类中的一致(不是绝对,父类为public则保持一直最好)。
class A { public void fun1() { System.out.println("fun1() in class A"); } } class B extends A { public void fun1()//覆写只调用覆写后的权限只能变大不能缩小 {//private<default<public System.out.println("fun1() in class B"); } } public class JavaDemo78 { public static void main(String args[]) { B b = new B(); b.fun1(); } } |
重载与方法的区别:
| 重载 | 覆写 |
概念 | 方法与类名称相容,参数的个数或类型不同 | 方法名称、访问权限、参数的类型和个数一样 |
范围 | 同一个类内 | 发生在继承关系中,在子类中实现 |
super关键字:当子类对象实例化时在子类的构造方法中默认隐含了一个super()方法,此代码作用调用父类中的默认的无惨构造方法。
格式:1、super():根据里面传入的参数去调用父类中指定的构造方法,默认情况下调用无惨构造方法。
class A { private String name; private int age; public A() { System.out.println("A() in class A"); } public A(String name) { System.out.println("A(String name) in class A"); } public A(String name,int age) { System.out.println("A(String name,int age) in class A"); } } class B extends A { private String school; public B(String name,int age,String school) { //默认的super()已经不能满足参数要求了 super(name,age); //指定调用父类中特定的构造方法把name、age传到父类特定的构造方法中 } } public class JavaDemo80 { public static void main(String args[]) { new B("Rock",23,"school"); } } |
格式:2、super.方法():由子类调用父类中指定的方法(方法被覆写了)。
class A { public String say() { return "hello"; } } class B extends A { public String say() {//return this.say()+" world!!!";默认行为 return super.say()+" world!!!"; //使用super关键字调用父类中指定的特定方法 } } public class JavaDemo81 { public static void main(String args[]) { System.out.println(new B().say()); } } |
this与super的区别:this与super在使用上很相似,都可以调用方法、属性,构造方中法都必须放在首行。
class A { String name = "Rock"; public A() { System.out.println("构造方法A"); } } class B extends A { String name = "Lee"; public B() { super();//super调用构造方法同this一样必须方法第一行 } public String say() { return super.name;//super调用父类属性 } } public class JavaDemo82 { public static void main(String args[]) { System.out.println(new B().say()); } } |
| ||
| This | Super | |
使用范围 | 调用分类中的的方法或属性 | 从子类中调用父类中的方法或属性 | |
调用范围 | This.本类属性,从本类中查找 | Super.父类属性,从父类中查找 | |
调用方法 | This.本类方法,从本类中查找 | Super.父类方法(),从父类中查找 | |
调用构造方法 | 放在本类构造方法的首行,构造方法需要有一个出口(至少有一个构造方法没有被this调用) | 放在子类构造方法中,默认隐含一个super()调用父类中的默认构造方法 | |
特殊点 | This表示当前对象 | 无 | |
范例1:
class Person {//super关键字的使用 private String name; private int age; public Person(String name,int age) { this.setName(name); this.setAge(age); } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public String say() { return "My name is "+this.name+"\nMy age is "+age; } } class Student extends Person { private String school ; public Student(String name,int age,String school) { super(name,age) ; this.setSchool(school) ; } public void setSchool(String school) { this.school = school; } public String getSchool() { return this.school ; } public String say() { return super.say()+"\nMy school is "+this.school; //return "My name is "+getName()+"\nMy age is "+getAge()+"\nMy school is "+this.school; } } public class JavaDemo83 { public static void main(String args[]) { Student s = new Student("李岩",23,"东城区24中"); System.out.println(s.say()); } } |
范例2:
//为了简单程序暂时不封装 class Employee { String name; int age; float salary; Manager mgr = null;// 类的引用表示一个雇员有一个领导 public Employee(String name,int age ,float salary) { this.name = name; this.age = age; this.salary = salary; } public String say() { return "\n姓名:"+name+"\n年龄:"+age+"\n薪水:"+salary; } } class Manager extends Employee { int number; public Manager(String name,int age,float salary,int number) { super(name,age,salary); this.number = number; } public String say() { System.out.println("\n"); return super.say()+"\n管理人数:"+this.number; } } public class JavaDemo84 { public static void main(String args[]) { Employee e = new Employee("李岩",23,1000); Manager m = new Manager("李小岩",33,2000,15); e.mgr = m;//m是e的领导 System.out.println("雇员信息:"+e.say()); // 为了防止mgr的内容为空,如果为空则肯定出现NullPointerException if(e.mgr != null) { System.out.println("经理信息:"+e.mgr.say()) ; } } } |
class Array{ private int[] temp = null; private int count = 0;
public Array(int len){ if (len>0){ this.temp = new int[len]; }else{ this.temp = new int[1]; } } public boolean add(int i){ if (this.count<this.temp.length){ this.temp[this.count] = i; this.count++; return true; }else{ return false; } } public int[] getArray(){ return this.temp; } } class ArraySort extends Array{ public ArraySort(int len){ super(len); } public int[] getArray(){ java.util.Arrays.sort(super.getArray()); return super.getArray(); } } public class J{ public static void main(String[] args){ Array arr = new ArraySort(6); System.out.println(arr.add(4)); System.out.println(arr.add(9)); System.out.println(arr.add(2)); System.out.println(arr.add(1)); System.out.println(arr.add(3)); System.out.println(arr.add(7)); System.out.println(arr.add(8)); print(arr.getArray()); } public static void print(int arr[]){ for (int i : arr ){ System.out.print(i+"\t"); } } } |
final:(类、变量、方法)
1、final标记的类不能被继承
2、final标记的方法不能被子类覆写
3、final标记的变量为常量,只能赋值一次,final标记的变量最好用大写字母表示。 全局常量:public static final
抽象类中包括:1、已定义好的方法 2、未定义方法的方法名
抽象类:就是包含一个抽象方法的类
抽象方法:一个只有声明而没有实现的方法
抽象类与普通类的差别:
1、比普通类的定义中多出一个抽象方法,普通类的所有定义在抽象类中都可以使用。
2、在类声明处需要用abstract声明抽象类,抽象方法也必须用abstract声明。
抽象类本身不能被直接实例化:
//定义抽象类,使用abstract abstract class A { public void talk() { System.out.println("public void fun2() in class A"); } public abstract void fun(); } public class JavaDemo85 { public static void main(String args[]) { new A();//抽象类本身无法直接实例化 } } |
抽象类使用规则:
1、抽象类不能直接实例化,不能用new去实例化对象。
2、抽象类只需要声明,不需要实现。、
3、含有抽象方法的类必须被声明为抽象类,抽象类必须有子类,子类必须覆写抽象类中的所有抽象方法。
abstract class A { public void talk() { System.out.println("public void talk() in class A"); } public abstract void fun(); } class B extends A {//B是一个普通类 //抽象类的子类要覆写抽象类中的全部抽象方法 public void fun() { System.out.println("public void fun() in class B extends A"); } } public class JavaDemo86 { public static void main(String args[]) { B b = new B(); b.talk(); b.fun(); } } |
子类如果不是抽象类,则必须覆写抽象类中的全部方法。抽象类属于Java的单继承模式。
子类对象实例化时依然按照先实例化父类中的属性,在实例化本类中的属性。
final可以声明一个类,但此类是一个不能有子类的父类,而抽象类本身又必须有子类。
接口:是抽象方法和常量的集合。接口中包括:常量、抽象方法。
抽象类中包含抽象方法,如果类中都是抽象方法时,则用接口表示。
接口中包括全局常量:public static final 接口访问权限永远是:public
interface A { //定义常量 //public static final String INFO = "Rock";简写为: String INFO = "Rock";//public static final 自动加在前面 //public abstract void say();//简写为: public void say();//abstract } |
接口在程序中叫做实现,即一个接口必须通过子类实现。
interface A {//定义常量 String INFO = "Rock"; public void say(); } class X implements A {//子类要实现接口中的全部抽象方法覆写 public void say() { System.out.println("Information :"+INFO); } } public class JavaDemo88 { public static void main(String args[]) { X x = new X(); x.say(); } } |
一个类可以同时实现多个接口:
interface A { String INFO = "Rock"; public void say(); } interface B { String NAME = "Lee"; public void talk(); } class X implements A,B { public void say() { System.out.println("interface A :"+INFO); System.out.println("interface B :"+NAME+" in say()"); } public void talk() { System.out.println("interface B :"+NAME); System.out.println("interface A :"+INFO+" in talk()"); } } public class JavaDemo89 { public static void main(String args[]) { X x = new X(); x.say(); x.talk(); } } |
一个普通类同时继承一个抽象类和实现两个接口:
interface A { String INFO = "Rock"; public void say(); } interface B { String NAME = "Lee"; public void talk(); } abstract class C { public abstract void fun(); } class X extends C implements A,B//先抽象类在接口 { public void say() { System.out.println("interface A :"+INFO); System.out.println("interface B :"+NAME+" in say()"); } public void talk() { System.out.println("interface B :"+NAME); System.out.println("interface A :"+INFO+" in talk()"); } public void fun() {//调用interfac A,B中被覆写的方法 say(); talk(); } } public class JavaDemo90 { public static void main(String args[]) { X x = new X(); x.fun(); } } |
一个新的接口可用extends继承一个已有的接口,接口可以多继承。但类不可以。
interface A { public void printA(); } interface B { public void printB(); } interface C extends A,B {//接口C继承接口A,B接口可以多继承多个父类 public void printC(); } abstract class D implements C { public abstract void printC(); //如果抽象方法同名,则在子类中只需要实现一次即可 } class X implements C { public void printA() { System.out.println("AAAAAAAAAAAA in class X"); } public void printB() { System.out.println("BBBBBBBBBBBB in class X"); } public void printC() { System.out.println("CCCCCCCCCCCC in class X"); } } public class JavaDemo91 { public static void main(String args[]) { X x = new X(); x.printA(); x.printB(); x.printC(); } }
|
如果抽象方法同名时,则在子类中只需要实现一次即可。
面向对象高级——04
多态性:
1、方法的多态性(重载):同一个方法根据传入的参数不同,完成的功能也不同。
2、对象的多态性。
面向对象程序开发的思路:建议:永远不要继承一个普通类。
子类对象与父类对象的转换:
1、向上转换:子类对象向父类对象转换
自动转型:父类对象=子类对象
2、向下转换:父类对象向子类对象转换
强制转型:子类对象=(子类)父类对象
对象的多态性是在继承上的一种扩展,所以程序要先有继承关系才能使用多态性
class A { public void say1() { System.out.println("say1() in class A"); } public void say2() { this.say1(); } } class B extends A { public void say1() { System.out.println("say1() in class B extends A"); } public void say3() { System.out.println("say3() in class B"); } } public class JavaDemo92 { public static void main(String args[]) {//向上转型:父类对象为子类对象实例化 A a = new B();//如果一个方法被子类覆写了,子类与父类发生间发生转换时 a.say2();//则自动调用已经被覆写过的方法(子类中的方法) //a.say3(); 转型后看不到本类中的方法 //向下转型:子类对象为父类对象实例化 B b = (B)a; b.say2();//找子类中被覆写后的方法 } } |
如果一个方法被子类覆写了,子类与父类发生间发生转换时,则自动调用已经被覆写过的方法(子类中的方法)。
class A { public void say1() { System.out.println("say1() in class A"); } public void say2() { this.say1(); } } class B extends A { public void say1() { System.out.println("say1() in class B extends A"); } public void say3() { System.out.println("say3() in class B"); } } public class JavaDemo93 { public static void main(String args[]) { A a = new A(); a.say2(); B b = (B)a;//出现ClassCastException错误 //两个类有关系了才能转型,现有向上转型,才能有向下转型 } } |
两个常见错误:1、ClassCastException(两个对象间没有任何关系而进行转型)
2、NullPointerException(空间指向异常)
对象多态性使用1:
class A { public void say1() { System.out.println("say1() in class A"); } public void say2() { this.say1(); } } class B extends A { public void say1() { System.out.println("say1() in class B extends A"); } public void say3() { System.out.println("say3() in class B"); } } public class JavaDemo94 { public static void main(String args[]) {//对象多态性的使用 //一个print方法可以接收A、B类的对象,并调用其中的方法打印 //A类对象调用say2()方法 B类对象调用say2()、say3()两个方法 print(new B()); //如果A类有20个子类,则此方法还要在写20遍 } public static void print(A a) { a.say2(); } public static void print(B b) { b.say2(); b.say3(); } } |
package democlass; class A{ public void fun1(){ System.out.println("A---------fun1()"); } public void fun2(){ this.fun1(); } } class B extends A{ public void fun1(){ System.out.println("B extends A ---------------fun1()"); } public void fun3(){ System.out.println("B------------fun3()"); } } public class J81{ public static void main(String args[]){ A a = new A(); a.fun2(); System.out.println(); a = new B(); B b = (B)a; b.fun2(); b.fun3(); } } |
instanceof是关键字,不是方法,判断对象和类是否有实例化关系。
class A { } class B extends A { } public class JavaDemo96 { public static void main(String args[]) { //A a = new B();//a被子类对象实例化后,既是A类对象也是子类B的对象 A a = new A(); System.out.println(a instanceof A); System.out.println(a instanceof B); } } |
对象多态性使用2:
class A { public void say1() { System.out.println("say1() in class A"); } public void say2() { this.say1(); } } class B extends A { public void say1() { System.out.println("say1() in class B extends A"); } public void say3() { System.out.println("say3() in class B"); } } class C extends A { public void say1() { System.out.println("say1() in class C extends A"); } public void say4() { System.out.println("say4() in class C"); } } public class JavaDemo95 { public static void main(String args[]) { print(new A()); } public static void print(A a) { a.say2(); //缺少一个对象是否是某一个类的实例判断 if (a instanceof B) { B b = (B)a; b.say3(); } if (a instanceof C) { C c = (C)a; c.say4(); } } } | ||
抽象类与接口的区别 | ||
| 抽象类 | 接口 |
组成 | 普通方法、抽象方法、常量、变量、全局常量、构造方法 | 抽象方法、全局常量 |
定义 | Abstract | Interface |
继承 | extends | Implements |
限制 | 一个子类只能继承一个抽象类 | 一个子类可以同时实现多个接口 |
关系 | 一个抽象类可以实现多个接口 | 接口不能继承抽象类,只能实现多个接口 |
一个抽象类中可以包含多个接口 | 一个接口中可以包含多个抽象类 | |
设计模式 | 模板设计 | 工厂设计、代理设计 |
两个一起操作完成适配器设计模式 | ||
实例化 | 通过对象的多态性,用子类进行实例化操作 | |
继承限制限制 | 单继承限制 | 单继承、多继承 |
特性 | - | 表示一个标准,一种能力 |
如果抽象类和接口都可以使用,优先使用接口(避免单继承)