JAVA面向对象之代码块 继承 方法的重写 super关键字与重写toString()方法介绍
2018-01-10 21:30
627 查看
JAVA面向对象之代码块与继承
代码块分类
局部代码块
作用:限制变量生命周期 书写位置:在方法中
构造代码块
开发中很少使用 书写位置:类中 方法外 调用时机:如果你有构造代码块 系统会帮你调用 帮你在创建对象时调用
静态代码块(一定是被static修饰)
依赖类 随着类的加载而加载 注意:只加载一次(系统只创建一次 不管你调用多少对象) 应用场景:U盘装载驱动程序(第二次插入U盘,不会再加载驱动程序) 加载驱动(数据库驱动 JDBC)
同步代码块(多线程)
这里暂时不做介绍 后续给予说明
代码示例
public class Demo24 { //第三代码块 { int a = 10; System.out.println(a); System.out.println("我是Demo24构造代码块"); } public static void main(String[] args){ Person2 person = new Person2(); person.name = "张三"; person.age = 15; person.sayHi(); System.out.println("我是main函数中得普通方法"); { System.out.println("我是局部代码块"); } Person2 person1 = new Person2("李四",22); } } class Person2{ String name; int age; //第一个代码块 static { System.out.println("我是person类的静态代码块"); } //第二个代码块 { //每一个对象 都会调用同一个方法 这时可以使用 sleep(); System.out.println("我是构造代码块"); } public Person2(){ System.out.println("我是无参数的构造方法"); } public Person2(String name, int age){ this.name = name; this.age = age; System.out.println("我是有参数的构造方法"); } public String getName(){ return name; } public void setName(){ 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("睡觉"); } }
运行结果
我是person类的静态代码块 睡觉 我是构造代码块 我是无参数的构造方法 姓名:张三年龄:15 我是main函数中得普通方法 我是局部代码块 睡觉 我是构造代码块 我是有参数的构造方法 姓名:李四年龄:22
解释
当程序运行时 会先加载Demo01.class文件,进入.class文件后,会寻找静态代码块,如果没有,会继续寻找构造代码块,由于没有 4000 Demo24类的实例对象,所有构造代码块与构造方法均不会执行,如果另外新建一个类,Demo25,在Demo25类中建立Demo24类的实例 对象,Demo24类中的构造代码块与构造方法便会执行,之后会首先寻找main函数,找到main函数后,(局部代码块定义在方法中,在该 方法中并没有优先级)会首先遇到Person2类,遇到Person2 person = new Person2();这时会加载Person2类, 加载Person2.class文件,静态代码块与静态方法和静态属性一样,会随着类的加载而加载,存放在方法区的静态区,与对象无关,所 以在加载Person2.class文件时,会将static代码块一同加载,所有会输出'我是Person类的静态代码块',之后需要new一个对象, 继续执行Person2类中的代码,执行时,会先寻找有没有构造代码块(构造代码块存放在类中方法外,优先级高于构造方法);发现有构 造代码块,即先执行构造代码块,构造代码块中有sleep方法,故先执行sleep方法,打印'睡觉',之后执行下一句,打印'我是构造代码 块',构造代码块执行之后,会执行相应的构造方法(有参或者无参),构造代码块优先于构造方法执行,与构造代码块的位置无关,new 对象的时候没有传递参数,所有这里调用无参构造方法,打印'我是无参数的构造方法',之后回到Demo01函数,对对象中的变量进行赋 值,赋完值后,调用对象的sayHi方法,打印'姓名:张三','年龄:15',随后执行到打印语句,打印出"我是main函数中得普通方法", 之后遇到局部代码块,打印"我是局部代码块"(顺序执行),当new第二个Person2对象时,静态代码块不会再执行,即在函数运行过 程中,只会加载一次,非静态构造代码块将会继续加载,第二次new对象时候,先执行构造代码块,构造代码块中有sleep方法,所有会 先执行sleep方法,打印"睡觉",随后打印"我是构造代码块",new对象时候,传进来了参数,所有会调用Person2类中的有参数构造 方法,打印"我是有参数的构造方法",赋值后,调用sayHi方法,打印"姓名:李四年龄22",函数运行结束.
继承
继承特点
1.减少你的代码量 2.让类与类之间产生关联(产生 父子的)
继承弊端
当父类中添加新德属性时候,比如白血病,子类即使不想继承这个属性,却还是由于 继承的关系,自动得到了白血病这个属性
注意
1.继承时 可把多个类中 相同的功能或方法 抽取出来 重新构造一个类出来 把这些类建立 继承关系 2.建立继承关系的同时 一定要符合逻辑(切记不要为了继承而继承) 3.继承使用关键字:extends
举例
继承: 手机类 <打电话 发短信 玩游戏> 苹果手机类 继承 手机类 <打电话 发短信 玩游戏 爆炸> 小米手机类 继承 手机类 <打电话 发短信 玩游戏 暖手功能>
项目经理:姓名 工资 工号 分红 程序员:姓名 工资 工号 项目经理 继承 程序员 就继承了姓名 工资 和 工号 ,特有功能 分红 这样不行 不符合逻辑 应该是相同的功能抽取出来 员工类 姓名 工资 工号 项目经理 和 程序员 继承员工类 这样才符合逻辑
注意
如果是继承关系 一定符合什么是什么 项目经理是员工 子类是父类的
动物 猫 狗 马 猫 是 动物 √ 动物 是 猫 × 水果(父类) 香蕉 苹果 橘子 水果 是 香蕉 × 香蕉 是 水果 √
继承的写法
class 子类 extends 父类{ }
代码示例
/* * 猫类 * 姓名 颜色 种类 会睡觉 会抓老鼠 * 狗类 * 姓名 颜色 种类 会睡觉 会啃骨头 */ // 抽取出 相同部分 组成 动物类 public class Demo02{ public static void main(String[] args){ Cat cat = new Cat(); cat.name = "汤姆"; cat.color = "灰色"; cat.kind = "灰猫"; cat.sleep(); cat.sayHi(); } } class Animal{ String name; String color; String kind; public void sleep(){ System.out.println("睡觉"); } public void sayHi(){ System.out.println("姓名:" + name +"颜色:" + color + "种类:" + kind); } } class Cat extends Animal{ public void hitMouse(){ System.out.println("抓老鼠"); } } class Dog extends Animal{ public void eatBone(){ System.out.println("啃骨头"); } }
运行结果:
抓老鼠 睡觉 姓名:汤姆颜色:灰色种类:灰猫
JAVA中的继承
注意
1.java 只允许 单继承(多继承 可以 使用 接口 来间接实现) 2.java 中 允许 多层继承(爷爷 父亲 儿子 孙子 重孙子....) java中 最顶层的父类(最基础类) Object类 如果我这个类没有写 继承哪个父亲 默认就是继承 Object类
1.如果我要使用 这些 类中 共有的方法(属性) 使用 哪个类? 创建当前继承中最 顶端的 类 去使用 2.如果我要使用 这些 类中 特有的方法(属性) 使用 哪个类? 创建当前继承中 最末端类 去使用
代码示例
public class Demo03 extends Object{ } //A类 爷爷类 B类 是父亲 C类 是 孙子类 //A类中又name C类中 会叫爷爷 class A extends Object{ String name; } class B extends A{ } class C extends B{ public void speak(){ System.out.println("会叫爷爷"); } }
构造方法能不能被继承?
爷爷 父亲 儿子 爹 和 儿子 都用同一中 方法生出来 行吗? 乱 奶奶不愿意 妈妈不愿意 构造方法是不能被继承的 为了保证继承的完整性 在你创建对象的时候 如果你不调用 父类的构造方法 系统会帮你去调用 父类的无参构造方法
代码举例
public class Demo04{ public static void main(String[] args){ Son son = new Son(); son.name = "张三"; son.sayHi(); //有参构造对象 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();//调用父类的 无参构造方法 System.out.println("我是儿子类的无参构造方法"); } //有参的 public Son(String name){ //如果你没有在子类的构造方法中 调用父类的构造方法 //系统 会默认 给你的子类 构造方法中 添加一行代码 super(); //系统帮你调用父类的构造方法 this.name = name; System.out.println("我是儿子类的有参构造方法"); } }
输出结果
我是爸爸类无参的构造方法 我是儿子类无参构造方法 张三 我是爸爸类无参的构造方法 我是儿子类有参的构造方法 小明
结果解释
当new一个Son对象时,由于没有传进去参数,所以会先调用儿子类的无参构造方法, 由于Son类是Father的子类,所有在子类的构造方法中会自动调用父类的无参构造方 法,从而实现Son类的实例对象同时具有Son类与Father类的属性与方法,因此先打印 父类无参构造方法中的"我是爸爸类的无参构造方法",之后返回子类构造方法,打印 子类无参构造器中得"我是儿子类无参构造方法",之后对Son的nane属性赋值,调用s ayHi方法将姓名打出 第二次new一个Son类对象的时候,传进去姓名这个参数,所有会调用Son类中得有参 构造方法,该有参构造方法中第一句会先执行super(),即会先执行父类无参构造方 法,向上调用父类构造方法时,没有传进去参数,所有不会调用父类有参构造方法,打 印"我是爸爸类无参构造方法"后,返回子类,即Son类,打印"我是儿子类有参构造方 法",然后将姓名赋值,随后返回main函数,调用sayHi方法将name打印出来.
super关键字
super 用于指向子类对象中的父类对象(构造方法) 相当于父类的对象 super 调用对象 super.对象 super 调用方法 super.方法() super(); 调用父类的构造方法 this(); 调用的是本类的构造方法
代码示例
public class Demo05{ public static void main(String[] args){ TestB b = new TestB(); b.fun(); } } class TestA{ int num1 = 10; int num2 = 20; public void sayHi(){ System.out.println("我是父类的sayHi方法"); } } 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(this.num3); //10 } }
思考:如果父类中没有无参构造方法 咋整?
建议:不管是父类 还是 子类 构造方法一定要写全,避免出现问题
代码举例
public class Demo04{ } 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); } }
方法的重写
思考: 如果父类 和 子类的 方法 重名了,咋整?能不能重名? 答案是可以 方法的重写
注意
1.方法的声明完全一致的 叫方法的重写 2.方法的重写建立在类与类之间有继承关系(子类重写父类的方法)
Override(重写)和Overload(重载) 的区别
1.重写前提:需要继承关系 重载:在同一个类里面实现 2.重写:需要方法的声明完全一致 重载:相同的功能,不同的实现方式 只跟参数有关
代码示例
public class Demo07{ public static void main(String[] args){ IOS8 ios8 = new IOS8(); ios8.siri(); //如果直接打印对象 相当于 系统帮你打印时 调用 toString()方法 System.out.println(ios8); //输出haha System.out.println(ios8.toString()); //输出haha } } class IOS7{ public void call(){ System.out.println("打电话"); } public void siri(){ System.out.println("说英文"); } } class IOS8 extends IOS7{ //方法的重写:对父类的方法 进行一个功能上的升级 //调不调父类的方法 要根据实际情况 public void siri(){ //中 英文都会说 super.siri(); //调用父类的方法 System.out.println("会说中文"); } //重写toString()方法 //利用toString方法 来写介绍自己的方法 public String toString(){ return "haha"; } }
重写toString()方法介绍
toString方法是Object类中的一个方法,故所有继承Object类的类,这些类中都有toString方法; 假设有一个类为Animal,他的一个对象为animal,则System.out.println(animal), 打印出来的是一个全限定类名com.lanou3g.IOS7@33909752,而打印System.out.println(animal.toString), .lanou3g.IOS7@33909752,即包名+类名+@33909752,说明打印animal与打印animal.toString()的结果是一样的,toString()方法写完整则是 public String toString(){},即说明toString方法是有返还值的,即打印animal.t oString()的结果,打印的是toString()函数中return语句返还的值,而打印animal 的结果又与打印animal.toString()方法的值相同,说明打印对象名所得到的结果就 是toString中return语句返还的结果,所有重写Object类中得toString方法,改变re turn语句的返还值,然后直接打印对象名,便可以得到自己想要的结果.具体结果如上面代码所示
实例练习继承关系
需求
老师类 学生类 * 无参 有参构造 set/get方法 成员变量私有化 介绍自己的方法 属性:姓名,年龄 * 行为:吃饭 * 老师有特有的方法:讲课 * 学生有特有的方法:学习
代码实现
package com.lanou3g; public class Demo08 { public static void main(String[] args) { //创建一个学生 Student student = new Student("王龙",15,1); System.out.println(student); Teacher teacher = new Teacher("刘",13); System.out.println(teacher); } } class Person1{ //属性 //继承中private修饰的变量 是不能直接访问的 但可以间接访问的 private String name; private int age; //构造方法 public Person1() { } public Person1(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() { // TODO Auto-generated method stub return "姓名:" + name + "年龄" + age; } } //学生类 class Student extends Person1{ //学号 private int num; public int getNum() { return num; } public void setNum(int num) { this.num = num; } //构造方法 public Student(){ } //有参 public Student(String name, int age, int num) { //直接调用父类的构造方法 完成赋值初始化 //为了保证继承的完整性 在子类构造方法中 //第一行 必须调用父类的构造方法(无参 有参都行) super(name,age); //特有属性 直接赋值就行 this.num = num; } public void study() { System.out.println("学生在学习"); } //介绍自己的方法 @Override public String toString() { //可以在父类的基础上 添加自己特有的属性 去打印 return super.toString() + "学号:" + num; } } //教师类 class Teacher extends Person1 { public Teacher(){ } public Teacher(String name, int num) { super(name,num); } public void teach() { System.out.println("老师会讲课"); } @Override public String toString() { // TODO Auto-generated method stub return super.toString(); } }
相关文章推荐
- JAVA面向对象基础:继承、变量隐藏、方法重写、包、修饰符、this、super
- JAVA基础再回首(六)——父与子的继承、super关键字、方法重写、方法重载
- Java面向对象-Java类的继承及super关键字
- JAVA第七节-继承,继承中方法重写,继承的初始化顺序,final关键字,super关键字,object类
- 黑马程序员——Java基础---面向对象代码块和继承和this和super和重写和重载和final
- java中的继承,继承中方法的重写,继承的初始化顺序,final关键字,super关键字
- 类、对象、继承、封装、多态、方法的重载和重写、Java的访问修饰符与其它关键字
- Java之面向对象例子(三) 多态,重写,重载,equals()方法和toString()方法的重写
- java面向对象基础课(继承,方法重写),图形界面=0912号
- 22-JAVA面向对象-重写toString()与equals()方法
- java学习之旅39--面向对象_12_继承_方法的重写
- java学习之路 之 高级类特性1-面向对象特征之二:继承及方法重写(override)
- PHP基础----面向对象相关特性----12类的继承与方法重写
- 有关JAVA的面向对象程序设计方法较全面介绍的一本书
- java方法的重载,重写,super,this,final关键字
- Java方法继承、方法重载、方法覆盖,多态和super关键字小总结
- 【原创】关于java对象需要重写equals方法,hashcode方法,toString方法 ,compareto()方法的说明
- java面向对象-super、继承、覆盖、多态、类加载、访问控制
- java方法的重载,重写,super,this,final关键字
- 面向对象第九课,面向对象三大基本特征,继承,Object用法,toString和equals方法