目录
一. 构造方法
1. 构造方法
2. 构造代码块
二. 继承
1. 基本概念
2. protected 关键字
3. 构造方法的访问特点
4. 成员变量的访问特点
5. 成员方法的访问特点
6. 向上向下转型
6.1 向上转型
6.2 向下转型
一. 构造方法
1. 构造方法
初始化一个新的对象 构建、创造对象的时候,所调用的方法
语法规则:
构造方法:修饰符 方法名-和类名相同(参数类型 参数名){方法体}
默认构造方法:
public class Phone {public Phone() {} }
public class Phone {//品牌private String brand;//价格private double price;//颜色private char color;public Phone() {}public Phone(String brand) {this.brand = brand;}public Phone(String brand, double price, char color) {this.brand = brand;this.price = price;this.color = color;}
[注]:
●构造方法没有返回值,也无void
●如果一个类我们没有给手动的写构造方法,系统会赠送一个无参的构造方法
●如果自己手动的写构造方法,系统则不送构造方法
●一般情况下,构造方法 不能直接调用 配合new关键字使用
●构造方法支持方法的重载
快捷键:
alt+shift+s
2. 构造代码块
在Java的类中使用{}声明的构造代码块,构造代码块在创建对象时被调用,每次创建对象都会调用一次,但是优先于构造函数执行。
// 构造代码块{System.out.println("构造代码块");}
作用:
和构造函数的作用类似,都能对对象进行初始化,并且只要创建一个对象,构造代码块都会执行一次。但是反过来,构造函数则不一定每个对象建立时都执行(多个构造函数情况下,建立对象时传入的参数不同则初始化使用对应的构造函数)。利用每次创建对象的时候都会提前调用一次构造代码块特性,我们可以实现诸如统计创建对象的次数等类似功能。
示例:
3.观察Payment类的定义,请对构造方法进行重构,减少冗余代码。public class Payment {// 构造代码块{System.out.println("[预加载]检查支付环境");System.out.println("[预加载]生成支付流水号");System.out.println("[预加载]启动支付插件");}// 构造方法public Payment() {System.out.println("默认支付金额¥0.01.");System.out.println("默认支付通道中国银联.");}public Payment(double pay) {System.out.println("支付金额¥" + pay);System.out.println("默认支付通道中国银联.");}public Payment(double pay, String way) {System.out.println("支付金额¥" + pay);System.out.println("支付通道" + way);} }
public class Demo03 {public static void main(String[] args) {Payment p1 = new Payment();System.out.println("============");Payment p2 = new Payment(777);System.out.println("============");Payment p3 = new Payment(7788,"建设银行");}
二. 继承
1. 基本概念
我们在学习过程中所有的基础都是类和对象,在类和对象这里我们有延伸出来几个非常重要的点----继承
作用:
共性抽取,提高代码的复用性(即多个类中,有共同的一些成员信息(变量、方法)可以提取到一个公共的类中,被提取的类继承了这个类,可以直接使用这些成员信息)
语法格式:修饰符 class 子类 extends 父类{子类可以直接调用父类非private修饰的成员方法和成员变量}
[注]:
●使用 extends 指定父类.
●子类会继承父类的所有 public 的字段和方法.
●对于父类的 private 的字段和方法, 子类中是无法访问的.
●子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用.//父类 超类 //protected --- 受保护的,子类中是可以访问 public class Person {protected String name;protected int age;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 void eat() {System.out.println("我有吃饭的方法");} }
//Student 子类 //修饰符 class 子类 extends 父类{ // 继承到父类非私有的方法和属性 //}public class Student extends Person {private int score;public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void study() {System.out.println(name + "正在认真的学习..");}}
public class Demo01 {public static void main(String[] args) {Person p1 = new Person();p1.eat();System.out.println("==========");Student s1 = new Student();s1.eat();s1.setName("zkt");s1.study();} }
●Java 中一个子类只能继承一个父类 (而C++/Python等语言支持多继承).
public class Demo02 {public static void main(String[] args) {C c = new C();c.eat();// A类的吃饭方法// 继承Object类System.out.println(c.toString());// zkt.knowledge02.C@15db9742} }class A {public void eat() {System.out.println("A类的吃饭方法");} }class B extends A {}//java中的继承是单继承,可以多级继承 class C extends A {}
●java中是单继承,一个子类只能有一个父类
●java中多重继承
●java中一父类可以有多个子类
2. protected 关键字
刚才我们发现, 如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 "封装" 的初衷. 两全其美的办法就是 protected 关键字.
protected --- 受保护的,子类中是可以访问
●protected关键字可以把字段和方法的访问权限控制在继承树内部,一个protected字段和方法可以被其子类,以及子类的子类所访问
class Person {protected String name;protected int age; }class Student extends Person {public String hello() {return "Hello, " + name; } }
3. 构造方法的访问特点
public class Fu {private int a;public Fu() {System.out.println("这是父类的无参构造方法");}public Fu(int a) {this.a = a;System.out.println("这是父类的有参构造方法");}}
public class Zi extends Fu {public Zi() {super();System.out.println("这是子类的无参构造方法");}public Zi(int a) {super(a);System.out.println("这是子类的有参构造方法");} }
public class Demo03 {public static void main(String[] args) {Fu fu1 =new Fu();System.out.println("===========");Fu fu2 =new Fu(10);System.out.println("===========");Zi zi1 =new Zi();System.out.println("===========");Zi zi2 =new Zi(10);} }
super--表示的是超类或者父类的意思
●super() 父类的构造方法
构造方法里面:
●默认调用父类无参构造方法super()
●如果显示的写了super(参数),默认的则不赠送
●super()一定是在第一行
●this()必须写在第一行,所以super()和this()不能同时出现public class Person {protected String name;protected int age;public String getName() {return name;}public Person(String name, int age) {super();this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}
public class Student extends Person {private int score;public Student() {//默认调用父类无参构造方法// super();//调用父类的有参构造方法super("zkt",18);}public Student(String name, int age, int score) {super(name, age);this.score = score;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public void hello() {System.out.println(name + "的年龄为"+age+"正在给您打招呼..");}}
public class Demo01 {public static void main(String[] args) {Student s1 =new Student();s1.hello();System.out.println("===========");Student s2 =new Student("zkt2",20,99);s1.hello();} }
4. 成员变量的访问特点
●=左边是谁,访问的就是谁
●就近原则 :局部>成员>父类的成员
public class Fu {protected int a =5;protected int b =10; }
public class Zi extends Fu {public int a = 10000;public String b = "这是子类的b";public int c = 999;//就近原则//局部>成员>父类的成员public void sayHello() {System.out.printf("hello,a的值为%s,b的值为%s,c的值为%s\n", a, b, c);System.out.printf("hello,a的值为%s,b的值为%s,c的值为%s\n", this.a, this.b, this.c);System.out.printf("hello,a的值为%s,b的值为%s,c的值为%s\n", super.a, super.b, c);} }
public class Demo01 {public static void main(String[] args) {Fu fu = new Fu();System.out.println(fu.a);System.out.println(fu.b);System.out.println("=========");Zi zi = new Zi();System.out.println(zi.a);System.out.println(zi.b);System.out.println("**********");zi.sayHello();System.out.println("**********");System.out.println("=========");// 父父new子 , =左边是谁,访问的就是谁Fu fu1 = new Zi();System.out.println(fu1.a);System.out.println(fu1.b); // System.out.println(fu1.c); 父类中没有此成员变量System.out.println("***********");} }
5. 成员方法的访问特点
●new的是谁,访问就是谁
●编译看左边运行看右边 new出来的是谁就是谁
public class Fu {public void sayHello() {System.out.println("这个是父类的sayHello方法");} }
方法的重写:
●发生在子类和父类中,如果父类所提供的方法不能满足子类的需求,则子类可以重写
●方法名相同,参数项相同,返回值也相同,子类的修饰符>=父类的修饰符,方法体不同public class Zi extends Fu {public void test() {System.out.println("这个是子类独有的方法");}//方法的重写://发生在子类和父类中,如果父类所提供的方法不能满足子类的需求,则子类可以重写//方法名相同,参数项相同,返回值也相同,子类的修饰符>=父类的修饰符,方法体不同public void sayHello() {System.out.println("这个是子类的sayHello方法");} }
public class Demo01 {public static void main(String[] args) {//new出来的是谁 调用就是谁Fu fu = new Fu();fu.sayHello();//new出来的是谁 调用就是谁Zi zi = new Zi();zi.test();zi.sayHello();//编译看左边运行看右边 new出来的是谁就是谁Fu fu1 = new Zi();fu1.sayHello(); // fu1.test(); 父类中没有声明此方法} }
6. 向上向下转型
6.1 向上转型
父类的引用指向子类的对象,一定是安全的
语法格式:
向上转型 ---直接赋值父类 对象名 =new 子类();
public class Animal {protected String name;public void eat() {System.out.println("这个是父类的吃饭方法");}public Animal(String name) {this.name = name;} }
public class Bird extends Animal {public String name = "扁扁";public String age;public Bird(String name) {super(name);}public void fly() {System.out.println("我是一直小小鸟,我在飞");} }
public class Dog extends Animal {public Dog(String name) {super(name);}@Overridepublic void eat() {System.out.println(name + "小狗正在吃饭");} }
public class Demo01 {public static void main(String[] args) {// 1.向上转型 ---直接赋值// 父类 对象名 =new 子类();父类的引用指向子类Animal a1 = new Bird("圆圆");System.out.println(a1.name);//成员变量看左边a1.eat(); //方法编译看左边,运行看右边 // a1.fly();Bird bird =new Bird("方方");Animal a2 = bird;}}
用途:
public class Demo02 {public static void main(String[] args) {Bird b1=new Bird("小鸟");Dog d1 =new Dog("小狗");eat(b1);eat(d1);}//2.向上转型,方法的参数public static void eat(Animal a1) {a1.eat();}//3.向上转型,方法的返回值public static Animal aaa() {return new Bird("小鸟1号");}//3.向上转型,方法的返回值public static Animal bbb() {return new Dog("小狗1");}}
6.2 向下转型
父类引用转为子类对象 可能会出现问题
语法格式:
子类类名 对象名 =(子类类名)父类的对象名;
可能会出现的问题:CalssCastException
解决上述问题:
使用instanceOf关键字先判断是否是子类类型
boolean b = 父类类型的对象 instance of 子类;
boolean b = 接口类型的对象 instance of 子类;public class Demo03 {public static void main(String[] args) {Animal a1 =new Dog("小狗"); // a1.fly();// ClassCastException--向下转型的时候,转的父类的对象一定要是目前真正的子类类型 // 子类类名 对象名 =(子类类名)父类的对象名;if(a1 instanceof Bird) {Bird b1 = (Bird) a1;b1.fly();}else {System.out.println("哎呦,你不是这种类型");}} }