Java中的代码块和继承
代码块
代码块分类:
1.代码块:限制变量的作用域(生命周期)
书写位置:在方法中
2.构造代码块(在开发中 很少使用)
书写位置: 在类中 方法
调用时机: 如果你有构造代码块 系统会帮你调用
帮你在创建对象之前调用 每次创建对象 都会调用
3.静态代码块(一定是被static修饰的)
静态代码块 依赖类 随着类的加载而加载
注意: 只加载一次(系统只调用一次 不管你创建了多少对象)
应用场景: 加载驱动(数据库驱动 JDBC)
4.同步代码块(多线程)
例如:
public static void main(String[] args) {
/*
{
System.out.println("我是局部代码块");
}
*/
Person person = new Person();
person.setName("吴彦祖");
person.setAge(18);
person.sayHi();
Person person2 = new Person("吴奇隆",18);
person2.sayHi();
}
}
/*
* 人名 年龄
* set/get 有参无参构造
*
*/
class Person{
private String name;
private int age;
static {
System.out.println("我是Person类的静态代码块");
}
{
//比如 我每个对象 都会调用同一个方法 这时候可以使用
this.sleep();
System.out.println("我是构造代码块");
}
//构造
public Person(){
System.out.println("我是无参数的构造方法");
}
public Person(String name, int age) {
this.name = name;
this.age = age;
System.out.println("我是有参的构造方法");
}
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 sayHi() {
System.out.println(name + " " + age);
}
//睡觉
public void sleep() {
System.out.println("睡觉");
}
继承
继承特点:
1.减少你的代码量
2.让类与类之间 产生关联(产生 父与子的关系)
继承使用的关键字:extends
继承的弊端:
1.继承时 可以把多个类中 相同的功能或方法抽取出来
重新构造一个类出来 把这些类 建立继承关系
2.建立继承关系的同时 一定要符合逻辑(切记不要为了继承而继承)
注意: 如果是继承关系 一定符合 什么是什么(项目经理 是员工 子类 是 父类)
继承的写法:
class 子类 extends 父类{
}
例如:
public static void main(String[] args) {
// 创建一个猫
// 子类继承了父类 方法和属性
Cat cat = new Cat();
cat.name = "大咪";
System.out.println(cat.name);
cat.kind = "中华田园";
System.out.println(cat.kind);
cat.color = "白色";
System.out.println(cat.color);
cat.catechMice();
cat.sleep();
}
//猫类
//姓名 颜色 种类 会睡觉 会抓老鼠
//狗类
//姓名 颜色 种类 会睡觉 会啃骨头
//抽取出 相同部分 组成 动物类
class Animal{
String name;
String color;
String kind;
//睡觉
public void sleep() {
System.out.println("会睡觉");
}
}
class Cat extends Animal{
//抓老鼠
public void catechMice() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
//啃骨头
public void chewBones() {
System.out.println("啃骨头");
}
}
Java中的继承
注意:
1.Java 只允许单继承(多继承可以使用借口来间接实现)
2.Java中 允许 多层继承(爷爷 父亲 儿子 孙子 重孙...)
Java中 最顶层的父类(最基础的类) Object类
如果我这个类 没有写 继承哪个父类 默认就是继承Object类
1. 如果我要使用 这些类中 共有方法(属性)
创建当前继承中 最顶端类 去使用
2. 如果我要使用 这些类中 特有方法(属性)
创建当前继承中 最末端的 类 去使用
//A类 是 爷爷类 B类是父亲类 C类是 孙子类
//A类中 有name C类中 会叫爷爷
class A{
String name;
}
class B extends A{
}
class C extends B{
public void call() {
System.out.println("会叫爷爷");
}
}
构造方法能否被继承
构造方法能被继承么?
答案是 构造方法不能被继承
例如:
public static void main(String[] args) {
Son son = new Son();
son.name = "儿子";
son.sayHi();
System.out.println("-------------");
//有参构造创建对象
Son son2 = new Son("小明");
son2.sayHi();
}
}
class Father{
String name;
//无参 有参 构造方法
public Father(){
System.out.println("我是爸爸类无参的构造方法");
}
public Father(String name) {
this.name = name;
System.out.println("我是爸爸有参的类构造方法");
}
public void sayHi() {
System.out.println(name);
}
}
class Son extends Father{
//无参的
public Son(){
//如果你这里没有在子类构造方法中 调用父类的构造方法
//系统会默认给你的子类构造方法中 添加一行代码
super();// 调用 父类的 无参构造方法
// super 相当于 父类的对象
System.out.println("我是Son类无参的构造方法");
}
public Son(String name) {
super();// 系统帮你默认调用父类的构造方法
this.name = name;
System.out.println("我是Son类有参的构造方法");
}
}
为了保证继承完整性 在你创建子类对象的时候
如果你不调用父类的构造方法 那么
系统会默认帮你去调用 父类的无参构造方法
关键字 super 和 this
super 关键字
super 代表的时: 父类的对象
super调用对象 super.对象
调用方法 super.方法
super(); 调用的父类无参构造方法
this(); 调用的本类构造方法
例如:
public static void main(String[] args) {
TestB b = new TestB();
b.fun();
}
class TestA{
int num1 = 10;
int num2 = 20;
}
class TestB extends TestA{
int num1 = 30;
public void fun() {
// 使用 this时 会先在本类中 寻找该属性
// 没找到 就去父类中寻找
System.out.println(this.num1);//30
System.out.println(this.num2);//20
System.out.println(super.num1);//10
}
}
如果父类没有无参构造方法怎么办?
如果父类没有无参构造方法怎么办?
例如:
class Phone{
String name;
//无参
// public Phone() {
//
// }
//有参
public Phone(String name) {
this.name = name;
}
}
class MI extends Phone{
//无参
public MI() {
// 子类的构造方法中 如果你什么都不写 会 默认调 父类无参的构造方法
// 如果 父类 没有无参的构造方法
// 就证明 父类当中 一定有 有参的构造方法
// 无论有参 还是无参 在子类 的 构造方法中
// 必须 要 调用一个 必须手动指定一个有参的构造方法去调用
super("Note2");
}
//有参
public MI(String name) {
super(name);
this.name = name;
}
}
建议: 不管是父类 还是子类 构造方法 一定要 写全 避免 出现问题
方法的重写
父类 和 子类 的方法 能不能重名?
是可以的
这样叫做 方法的重写
注意:
1.方法声明完全一致的时候 叫方法的重写
2.方法的重写 建立在类与类之间有继承关系(子类 重写 父类 的 方法)
例如:
public static void main(String[] args) {
IOS8 ios8 = new IOS8();
ios8.siri();
//如果直接打印对象 相当于 系统会帮你
//在打印时 调用 toString方法
System.out.println(ios8);
System.out.println(ios8.toString());
}
}
class IOS7{
public void call() {
System.out.println("打电话");
}
public void siri() {
System.out.println("说英文");
}
}
class IOS8 extends IOS7{
@Override // 注解 标识这个方法是重写父类方法
public void siri() {
//调不调父类的方法 要根据实际情况
super.siri();
}
/*
// 方法的重写: 对父类的方法 进行一个 功能上的 升级
public void siri() {
//中英文都会说
super.siri();//调用父类的方法
System.out.println("会说中文");
}
*/
// 重写 toString()方法
// 利用tostring方法 来写 介绍自己的方法
@Override
public String toString() {
return "哈哈";
}
}
当成员变量用 private修饰的时候 成员变量还能继承么?
当成员变量用 private修饰的时候 成员变量还能继承么?
例如:
public static void main(String[] args) {
Student student = new Student("苏茜孟", 21, 17120404);
System.out.println(student);
}
class People{
//继承中 private 修饰的 变量 是不能直接访问的
private String name;
private int age;
//构造方法
public People(){
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
//set/get方法
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("吃饭");
}
//介绍自己
@Override
public String toString() {
return "姓名: " + name + " " + "年龄: " + age + " ";
}
}
class Teacher extends People{
public Teacher() {
}
public Teacher(String name, int age) {
super(name, age);
}
public void teach() {
System.out.println("教书");
}
@Override
public String toString() {
return super.toString();
}
}
class Student extends People{
//学号
private int id;
//构造方法
public Student() {
}
public Student(String name, int age, int id) {
// 直接调用父类的 构造方法 完成初始化
// 为了保证继承的完整性 在子类构造方法中
// 第一行 必须 调用 父类的 构造方法(无参 有参 都行)
super(name, age);
// 特有属性 直接 赋值就行
this.id = id;
}
public void study() {
System.out.println("学习");
}
//介绍自己的方法
@Override
public String toString() {
//可以在 父类的基础上 添加自己特有的属性 去打印
return super.toString() + "学号: " + id;
}
}
Day.10