
继承(extends)
AextendsB
A继承了B,B是A的基类、父类(superclass)、超类,A是B的子类
继承注意事项:
-
子类可以继承父类的成员,但是不要为了减少重复代码而去继承,必须要有继承关系
public class AnimalTest { public static void main(String[] args) { // 实例化Dog Dog dog = new Dog(); // 对对象中的属性进行赋值 dog.name = "哈斯奇"; // 访问对象中的属性 System.out.println(dog.name); // null int age = dog.age; System.out.println(age); // 0 dog.color = "白色"; String str = dog.color; System.out.println(str); dog.run(); } } class Dog extends Animal{ } class Animal { int age; String name; String color; public void run() { System.out.println(this.name + "动物正在跑......"); } }
-
父类的私有成员不能被继承.
public class AnimalDemo { public static void main(String[] args) { Bird bird = new Bird(); // bird.color = "百色"; System.out.println(bird.color); // 彩色 bird.color = bird.getColor1(); System.out.println(bird.color); } } class Bird extends Animal1 { public Bird() { System.out.println("调用子类类无参构造"); // this.name = 12; 访问不到 color = "彩色"; } public Bird(String color) { System.out.println("调用了子类的带参构造"); this.color = color; } } class Animal1 { private String name ; String color; private String getColor() { return color; } public String getColor1() { return "黑色"; } public Animal1(String name , String color) { this.name = name; this.color = color; } public Animal1(String color) { System.out.println("调用父类带参构造"); this.name = name; } public Animal1() { System.out.println("调用父类无参构造"); this.name = "爱情鸟"; this.color = "白色"; } }
-
父类的构造方法不能被继承
-
创建子类对象时会先调用父类的无参构造器,然后再去调用子类的构造器
调用父类的构造器作用 : 为了初始化从父类继承下去的属性
super关键字
super关键字:代表的是父类的引用空间
作用:
-
如果子父类存在同名的成员时,在子类中默认是访问子类的成员,可通过super关键字指定访问父类的成员
代码展示:
import java.util.Scanner; public class AnimalTest1 { public static void main(String[] args) { // 默认值 : 整型 0 浮点型 0.0 布尔 false 引用 null , 字符 '\u0000' Dog2 dog = new Dog2(); dog.name = "你好"; Dog2 dog2 = new Dog2(); dog.print(); // System.out.println(name + "在吃饭"); Scanner input = new Scanner(System.in); System.out.print("请您从键盘输入颜色:"); dog.setColor(input .next()); String color = dog.getColor(); System.out.println(color); } } class Dog2 extends Animal2 { /* String color ; String name; int age; public void print() { System.out.println(name + "动物的名字为" + name + ",年龄为 age = " + age); } * */ String name = "12"; public void print() { System.out.println("调用了子类的print()的方法"); System.out.println(name + "在吃饭"); setColor("白色"); System.out.println("颜色为" + getColor()); // 颜色为 黑色 super.name = "占山"; super.print(); System.out.println(super.name); super.name = "占山"; } } class Animal2 { private String color ; /* private*/ String name; // 父类中的私有成员不能被继承 int age; public void setColor(String color) { // 有参无返回值 this.color = color; } public String getColor() { // 有返回值无参 return color; } public Animal2() { System.out.println("用调用了父类无参构造"); name = "你好呀小样"; age = 1 ; // color = "黑色"; } public void print() { System.out.println("调用了父类的print()方法"); System.out.println(name + "动物的颜色为" + color + ",年龄为 age = " + age); } }
-
在子类中可用super关键字来调用父类中的构造器
代码展示:
public class AnimalTest5 { public static void main(String[] args){ Shrap shrap = new Shrap("你好",23,"造成"); System.out.println(shrap); } } class Shrap extends Animal3 { public Shrap() { // super(); System.out.println("调用了子类的无参构造"); } String name ; int age; String color; public Shrap(String name ,int age ,String color) { // super(); // 调用父类无参构造 this.name = name ; this.age = age; this.color = color; System.out.println(super.name); System.out.println(super.age); System.out.println(super.color); } @Override public String toString() { return "[ 名字为 name = " + name + ",颜色为 color = " + color + ",年龄为 age = " + age + "]" ; } } class Animal3 { String name; // 默认值为null String color; // 默认值为null int age; // 默认值 为 0 public Animal3() { System.out.println("调用了父类中无参构造"); this.name = "niha1"; this.age = 1; this.color = "black"; } public Animal3(String name ,int age ,String color) { System.out.println("调用了父类的带参构造"); this. name = name ; this.age = age; this.color = color; } }
注意:
-
super关键字用来在子类中调用父类构造器时,必须是构造体中的第一条语句
-
this和super调用构造器时,不能同时出现在同一个构造体中
代码展示:
public class AnimalTest06 { public static void main(String[] args) { Cat cat = new Cat("你是","谁呀",45); System.out.println(cat.name); } } class Animal4 { String name ; String str ; int age; public Animal4() { // 构造器名 必须和类名 保持一致 System.out.println("调用父类的无参构造...."); name = "name" ; age = 12; str = "明天你好"; } public Animal4(String name ,String str,int age) { this.age = age ; this.str = str; this.name = name; System.out.println("执行了父类的带参构造"); } } class Cat extends Animal4 { String name ; String str; int age; public Cat() { System.out.println("调用了子类无参构造"); } // cName = "你是' // cStr = "谁呀" // cAge = age public Cat(String cName ,String cStr,int cAge) { // super();// 调用了父类的无参构造 this(cName,cStr); // 调用了当前类中带两个参的构造方法 // super(cName,cStr,cAge); // 调用了父类中带参构造器 System.out.println("调用了子类中三个参数的构造器"); System.out.println("调用了子类带三个参构造器"); age = cAge; } public Cat(String name ,String str) { System.out.println("调用了子类中两个参数的构造器"); this.name = name; this.str = str; } }
-
方法重写
什么时候进行方法重写? (方法重写的应用场景)
当父类的方法功能无法满足子类需求时,我们就进行方法重写
代码展示:
public class CarFactory {
public static void main(String[] args) {
BSJ bsj = new BSJ();
bsj.run(bsj.name);
}
}
class Car {
String name;
String color;
public void run(String name) {
System.out.println( name + "四个轮子跑的会很快");
}
public Car() {
System.out.println("调用了父类中的构造器");
}
}
class BSJ extends Car {
public BSJ() {
this.name = "保时捷";
this.color = "白色";
System.out.println("调用了子类中的构造器");
}
String name;
String color ;
// 重写run方法
// 子夫类的方法名&&形参必须保持一致
public void run(String name) {
System.out.println( name + " 我的四个轮子牛逼的很");
}
}
-
前提: 必须有继承关系
-
要求:
-
方法重写时,子父类的方法名&&形参&&方法返回值类型必须保持一致
代码展示:
// 子夫类的方法名&&形参必须保持一致 public void run(String name) { System.out.println( name + " 我的四个轮子牛逼的很"); } // 父类中的方法 public void run(String name) { System.out.println( name + "四个轮子跑的会很快"); }
-
方法重写时,子类的权限修饰符 > | = 父类的方法权限修饰符
代码展示:
// 父类中的run方法 private void run(String name) { System.out.println( name + "四个轮子跑的会很快"); } // 子类中重写父类中的run方法 // 重写run方法 public void run(String name) { System.out.println( name + " 我的四个轮子牛逼的很"); }
-
方法重写时,子类的返回值类型 < | = 父类的返回值类型
代码展示:
// 方法重写是,子类的返回值类型 < | = 父类的返回值类型 private String run(String name) { return name + "四个轮子跑的会很快"; } // 重写run方法,子类重写父类的run方法 public void run(String name) { System.out.println( name + " 我的四个轮子牛逼的很"); }
-
方法重写时,子类抛出的异常类型 < | = 父类抛出的异常类型
代码展示:
// 子类抛出的异常类型 = 父类抛出的异常类型 // 父类中的run方法,父类抛出的异常类型也是Exception private String run(String name) throws Exception { return name + "四个轮子跑的会很快"; } // 重写父类中的run方法, 子类抛出的异常类型 是Exception public void run(String name) throws Exception { System.out.println( name + " 我的四个轮子牛逼的很"); } // 子类抛出的异常类型 < 父类抛出的异常类型 // 重写run方法 ,子类抛出的异常类型 NoSuchFieldException public void run(String name) throws NoSuchFieldException { System.out.println( name + " 我的四个轮子牛逼的很"); } // 父类中的run方法,父类抛出的异常类型 private String run(String name) throws Exception { return name + "四个轮子跑的会很快"; }
-
instanceof关键字
作用:判断一个对象是否属于一个指定的类型
前提:判断的对象&&指定的类型必须有继承关系 (extends)| 实现(implements)关系
使用格式: 对象 instanceof 指定的类型
代码展示:
public class InstanceOfDemo {
public static void main(String[] args) {
Cat cat = new Cat();
boolean flag = cat instanceof Cat;
if(flag) {
System.out.println("属于");// 输出
}else {
System.out.println("不属于");
}
// 判断的对象与指定的类型必须存在实现关系 | 继承关系
BSJ bsj = new BSJ();
if(bsj instanceof Car) {
System.out.println("属于"); // 输出
}else {
System.out.println("不属于");
}
/* new Animal();*/
if(new Animal() /*对象*/ instanceof Dog /*指定的类型*/ ) {
System.out.println("属于");
}else {
System.out.println("不属于"); // 输出
}
}
}
abstract关键字
注意细节:
-
若方法没方法体,那方法必须使用abstract修饰
-
若类中有抽象方法,那该类必须用abstract修饰
代码展示:
abstract class Animal5 { String name ; String color; public abstract void sleep(); }
-
非抽象类继承抽象类时,非抽象类必须要实现抽象类中的所有抽象方法
代码展示:
abstract class Animal5 { String name ; String color; public abstract void sleep(); } class Fish extends Animal5 { public void sleep() { System.out.println(name + "在睡觉...."); } }
-
抽象类中可以定义抽象方法和非抽象方法
代码展示:
abstract class Animal5 { String name ; String color; public void println() { System.out.println("name = " + name + "\ncolor = " + color); } public abstract void sleep(); }
-
抽象类中也可不定义抽象方法
代码展示:
abstract class Animal5 { String name ; String color; public void println() { System.out.println("name = " + name + "\ncolor = " + color); } /*public abstract void sleep();*/ }
-
抽象类不能实例化,即:抽象类是不能创建对象的
为什么抽象类不能实例化?
答:因为抽象类若实例化了,就可以使用对象去调用抽象方法了,一旦调用了就没有意义了
编译错误截图:
代码展示:
abstract class Animal5 { String name ; String color; public static void print() { System.out.print("你哈" + "好呀"); } public void println(String name ,String color) { System.out.println("动物name = " + name + "\ncolor = " + color); } public abstract void sleep(); }
-
抽象类中存在构造器
既然抽象类不能实例化,那存在构造器有何意义?
抽象类的构造器是留给子类调用的,初始化从父类继承下去的属性的
代码展示:
abstract class Animal5 { String name ; String color; public static void print() { System.out.print("你哈" + "好呀"); } public void println(String name ,String color) { System.out.println("动物name = " + name + "\ncolor = " + color); } public abstract void sleep(); public Animal5() { System.out.println("调用了抽象类中无参构造"); } public Animal5(String name){ System.out.println("调用了抽象类中带一个参的构造器"); this.name = name; } public Animal5(String name ,String color) { this(name); // 调用本类中的带一个参数的构造器 System.out.println("调用了抽象类中带两个参构造"); this.color = color; } }
接口(interface)
-
作用:
- 程序的解耦(低耦合高内聚)
- 定义约束
- 拓展功能
-
接口定义格式:
代码展示:
// 接口定义格式如下: interface 接口名 { ...... }
-
注意事项:
-
在接口中的变量都是自定义常量,修饰符必须是public static final
/*public static final*/ int name = 0 ;
-
在接口中的方法都是抽象方法,修饰符是public abstract
/*public abstract*/ void clear();
-
接口不能实例化,接口可以声明变量
-
接口没有构造器
原因:因为接口中变量都是自定义常量,接口中的方法都是抽象方法
-
若一个非抽象类实现接口时,必须实现接口中的所有方法
实现接口的格式:
public class 类名 implements 接口1,接口2,接口3.....{ }
代码展示:
class UserDao implements Dao { @Override public User find() { return new User("张三",11,"创智博客创新科技园",13886952615L); } @Override public void delbyId(int id) { System.out.println("删除成功~~"); } @Override public void update(int id) { System.out.println("更新成功~~"); } @Override public void add(User user) { System.out.println("添加成功"); } } interface Dao { User find(); void delbyId(int id); void update(int id); void add(User user); }
接口&&类的关系: 实现关系
注意细节:
-
非抽象类实现一个接口时,必须实现该接口中的所有方法
-
一个类可以实现多个接口
public class 类名 implements 接口1,接口2,接口3.....{ // 实现接口中的方法 }
问:java支持多实现接口,为什么不支持多继承呢?
若支持多继承,假设多个父类中有相同成员,那子类就不知道要调用哪个同名成员了.
-
抽象类实现接口时,可实现接口中方法,也可以不实现
代码展示:
public class UserServiceTest { public static void main(String[] args) { Dao dao = new UserDao(); } } abstract class UserServiceImpl implements Service { public void addUser(){ System.out.println("添加成功"); } public void delUser() { System.out.println("删除成功"); } } interface Service { void addUser(); void delUser(); User findUser(); void updateUser(); }
-
多态
所谓多态?多态就是一个对象多种形态
即:父类引用类型变量指向了子类对象或者接口引用类型变量指向了实现类对象
多态的前提: 必须存在继承 | 实现关系
继承关系下的多态
父类类型 变量名 = new 子类对象();
比如:
Animal animal = new Dog();
多态的注意事项:
- 在多态情况下,子父类存在同名的成员变量时,默认会访问父类的成员变量
- 在多态情况下,子父类存在同名的非静态方法时,默认是调用子类的非静态方法
- 在多态情况下,子父类存在同名的静态方法时,默认是调用父类的静态方法
- 在多态情况下,不能直接访问子类特有的成员,若要访问,需要强转
总结:多态情况下,子父类存在同名的成员时,默认都会访问父类的成员,只有存在非静态同名方法时,才会方法调用子类的非静态方法,若要在多态情况下调用到子类的特有的成员,那么必须进行强制类型转换
多态的应用场合:
- 多态用于形参类型时,可接受更多类型的参数
- 多态用于返回值类型时,可接受更多类型的参数
多态的好处:提高了程序的可拓展性
代码展示:
public class AnimalTest4 {
public static void main(String[] args) {
Animal6 animal = new Snake("眼睛蛇", "白色",12.2);
// 多态情况下,子父类存在同名变量是,默认会方法父类的成员变量
System.out.println(animal.name);
// 多态情况下,子父类存在同名的非静态方法时,默认值会先调用子类中非静态方法
animal.play(); // 调用子类中的play()方法
// 多态情况下,子父类存在同名的静态方法时,默认是调用父类的静态方法
animal.print(); // 父类中的静态print()方法
Animal6.print(); // 父类中的静态print()方法
// 多态情况下,不能直接访问子类中特有的属性,若要访问,需要强转
Snake animal1 = (Snake) animal;
animal1.length = 1574;
System.out.println(animal1.length); // 12.2
// println(new Snake("蟒蛇","中色",100));
println(new Snake("蟒蛇","中色",100));
Animal6 println = println();
Snake println1 = (Snake) println;
// 在多态情况下不能访问子类中特有的属性,若要访问,需要强转
System.out.println(println1.length);
}
public static void println(Animal6 animal) {
System.out.println(animal);
}
public static Animal6 println() {
return new Snake("小鸡鸡","黑色",12);
}
}
class Animal6 {
// 属性
String name ;
String color;
// 编写成员方法
public void run() {
System.out.println(name + "什么动物正在跑");
}
public void eat() {
System.out.println(name + "动物正在吃东西.... ");
}
public void sleep() {
System.out.println(name + "动物正在睡觉....");
}
// 编写get 和set方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this. color = color;
}
// 无参构造器
public Animal6() {
System.out.println("调用了父类的无参构造");
}
// 带参构造器
public Animal6(String name ,String color ) {
System.out.println("调用父类的带惨构造");
this.name = name ;
this.color = color;
}
// toString()方法
public String toString() {
System.out.println("调用了父类中toString()方法");
return "[ name = " + name + ",color = " + color + "]";
}
public void play() {
System.out.println(name + "动物们正在开开心心的玩耍");
}
public static void print() {
System.out.println("父类中的静态print()方法");
}
}
class Snake extends Animal6 {
// 特有属性
double length;
String name;
String color;
public Snake() {
System.out.println("调用了子类的构造方法" );
}
public Snake(String name ,String color) {
System.out.println("调用了子类的带参构造");
this.name = name ;
this.color = color;
}
public Snake(String name ,String color,double length) {
// super(name ,color); // 调用了父类的无参构造
this(name,color);
System.out.println("调用了子类的带参构造");
this.length = length;
}
public void play() {
System.out.println("调用子类中的play()方法");
}
public static void print() {
System.out.println("子类中的静态print()方法");
}
public String toString() {
return "[ name = " + name + ",color = " + color + ",length = " + length + "]";
}
}
实现关系下的多态
接口引用数据类型 变量名 = new 实现类对象();
比如:
Dao userDao = new UserDao();
代码展示:
public class UserDaoTest {
public static void main(String[] args) {
Dao userDao = new UserDao();
User user = userDao.find();
System.out.println(user);
}
}
class UserDao implements Dao {
@Override
public User find() {
return new User("张三",11,"创智博客创新科技园",13886952615L);
}
@Override
public void delbyId(int id) {
System.out.println("删除成功~~");
}
@Override
public void update(int id) {
System.out.println("更新成功~~");
}
@Override
public void add(User user) {
System.out.println("添加成功");
}
}
interface Dao {
User find();
void delbyId(int id);
void update(int id);
void add(User user);
}