1、由于面向对象非常的抽象难理解,所以建议各位学习的时候一定要在代码中感受,切忌纸上谈兵,因为放在代码情境里更方便你的直观领悟,但是并不代表理论知识不重要,同样要掌握!!!
2、本篇文章所有的解释性语言都放在代码内部,仔细查看代码,并放到真实的运行环境中亲身感悟,动手跑起来,领悟今日份代码成功运行的快乐。
【承接上篇:面向对象(一)】
六、this关键字
概念
this代表本类对象的一个引用对象。
形式
this.name = name;
3、练习this的用法(两种情况)
3.1 变量名相同时
创建person类
package cn.tedu.thisdemo;
public class Person {
String name;
//构造方法
public Person() {}
public Person(String name) {
//成员变量name = 局部变量n
//变量使用时,有个就近原则。所以,等号左右两侧使用的都是局部变量name,左侧根本没找到成员变量
//name = name;
//1、当成员变量和局部变量同名时,优先使用局部变量;如果想要找到成员变量,通过this关键字调用本类的成员变量
//2、this代表的是本类的对象的引用。相当于底层帮你写了一行代码:Person this = new Person();
//3、this能调用的是本类的成员!!!可以是成员【变量】或者【方法】
this.name = name;
}
}
创建测试类
package cn.tedu.thisdemo;
public class Test_PersonThis {
//这个类用来测试this --- 变量名相同时
//总结:当变量名相同时,用this关键字调用成员变量
public static void main(String[] args) {
//无参构造对象
Person p = new Person();
//含参构造对象
Person p2 = new Person("大白");
System.out.println(p2.name);
}
}
控制器显示 : 大白
3.2 构造方法间的调用
创建Person2类
package cn.tedu.thisdemo;
public class Person2 {
//创建方法
public Person2() {
//2、在无参构造方法中,使用含参构造
this(13);//必须放在第一行
System.out.println("无参构造方法");
}
public Person2(int age) {
//1、在含参构造方法中,使用 无参构造方法
// this();
System.out.println("含参构造" + age);
}
}
创建测试类
package cn.tedu.thisdemo;
//测试this的使用:构造方法间的调用
public class Test_PersonThis2 {
public static void main(String[] args) {
//触发两个构造方法
//无参构造
Person2 p = new Person2();
//含参构造
Person2 p2 = new Person2(18);
}
}
七、继承
继承可以说是面向对象中经常用到的,算是重点内容,所以掌握好继承是必须的,要不然分析到多态的时候就会更加的蒙圈。加油!!!
1、概念
1.继承是面向对象最显著的一个特征
2.继承是从已有的类中派生出的新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。
3.java继承以使用已存在的类定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性的继承父类/超类/基类
4.这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发成本
特点
1.使用extends关键字,
2.相当于子类把父类的功能复制了一份
3.java只支持单继承;
4.继承可以传递(爷爷,儿子,孙子的关系)
5.不能继承父类的私有成员;
6.继承多用于功能的修改,子类可以拥有父类的功能的同时,进行功能的拓展
7.像是is 和 a 的关系
3、入门案例
为验证上述特点,所以设计了三个类进行测试:Grandfather、Father、Son
3.1 Grandfather类
package cn.tedu.extendsdemo;
public class GrandFather {
int age = 90;
public void game() {
System.out.println("下象棋...");
}
}
3.2 Father类
package cn.tedu.extendsdemo;
public class Father extends GrandFather {
//5、父类的私有成员,无法被子类继承
private int s = 20;
int sum = 10;
public void show() {
System.out.println("show()...");
}
}```
3.3 Son类
```java
package cn.tedu.extendsdemo;
//1、子类想要使用父类的功能,必须发生继承关系
//4、java只支持单继承/单根继承
public class Son extends Father {//7、继承是is a 的关系,是子类和父类发货所能了强制的依赖关系 --- 强耦合(不建议使用)
//2、当子类继承父类后,相当于把父类的功能复制了一份,可以随时使用父类的功能
//6、继承的传递性,不仅能用父类的,还能用爷爷类的功能
}
测试类
package cn.tedu.extendsdemo;
//测试继承的入门案例 -- 重点
public class Test_Extends {
public static void main(String[] args) {
//创建对象
// GrandFather gf = new GrandFather();
// gf.game();
// System.out.println(gf.age);
//创建父类对象测试
// Father f = new Father();
// f.show();//show()...
// System.out.println(f.sum);//10
//3、创建子类对象测试,能否使用父类功能
Son son = new Son();
son.show();//show()...
System.out.println(son.sum);//10
son.game();//使用爷爷的属性
System.out.println(son.age);
}
}
子类继承了父类的所有功能;父类继承了爷爷类的所有功能;所以相应的子类也能继承到爷爷的功能;
八、super关键字
1、 作用
1.通过super关键字可以使用父类的内容
2.super代表父类的一个引用对象
3.如果用在构造方法中,必须出现在调用位置的第一条语句!!(类似于this)
九、方法重写override
继承后,子类将拥有了父类的功能;
那么在子类中,可以添加子类特有的功能也可以修改父类的原有功能;
子类中方法签名与父类完全一样(包括方法的返回值,方法名和参数泪飙,完全一致)时,会发生覆盖\复写操作,相当于修改功能;
注意:
父类中的私有方法不能被重写;
子类重写父类方法时,修饰符要大于等于父类修饰符的权限;
十、继承的作用
局部的,成员的,父类的
package cn.tedu.extendsdemo;
//这个类用来测试 继承的 成员变量的使用
public class Test_UseExtend {
public static void main(String[] args) {
Son2 son2 = new Son2();
son2.study();
System.out.println();
}
}
//父类
class Father2{
int count = 5;
int sum = 30;
}
//子类
class Son2 extends Father2{
int sum = 20;
public void study() {
int sum = 10;
System.out.println(sum);//10,就近原则
System.out.println(this.sum);//20,使用了成员变量20
// System.out.println(count);//子类没有,只能使用父类的count -- 简写
//1、使用super关键字,可以在子类中,调用父类的功能
System.out.println(super.count);//5
System.out.println(super.sum);//30
}
}
2、成员方法的使用
继承方法,特有方法,重写方法
package cn.tedu.extendsdemo;
//用来测试继承中成员方法的使用
public class Test_UseExtend2 {
public static void main(String[] args) {
Er er = new Er();
er.eat();//重写前用的是父类的,重写后用的是子类的
er.sleep();//父类的
er.coding();//子类特有的
}
}
class Ba{
public void eat() {
System.out.println("重写前,嗯,真香...");
}
public void sleep() {
System.out.println("呼呼呼...");
}
}
class Er extends Ba{
//3、当需要修改父类的原有功能时,为了不修改源代码,子类可以方法重写
//方法重写:继承关系 + 子类的方法声明和父类一样
public void eat() {
// super.eat();//4、在子类中,测试父类的eat()真的没有影响吗? --真的没有,没有影响父类的源代码
System.out.println("重写后,吃吃吃...");
}
//1、子类可以使用父类的所有功能(除了private)
//2、子类可以使用父类的同时,还可以自己拓展
public void coding() {
System.out.println("code...");
}
}
总结:
方法重写的意义:当业务发生改变时,我们不能修改源代码,只能发生继承关系后,修改功能;
重写的前提:继承关系 + 子类的方法声明和父类一样;
子类必须有权限重写父类的方法。子类权限 >= 父类权限;
3、构造方法的使用
1.子类创建对象时,默认会去访问父类的无参构造
2.在构造方法的第一行,都有一条默认的语句:super();
3.父类在没有无参构造时,可以用super掉用父类的其他构造
package cn.tedu.extendsdemo;
//这个类用来测试继承中构造方法的使用
public class Test_UseExtends3 {
public static void main(String[] args) {
//创建子类对象测试
//2、子类创建对象时,会触发子类的无参构造,但是第一行隐藏着super()会主动去找父类无参构造
Sub s = new Sub();//自动匹配无参构造
}
}
class Baby{
public Baby(int a) {
System.out.println("Baby...无参构造");
}
}
class Sub extends Baby{
public Sub(){
//1、默认存在,隐藏不显示,会自动调用父类的无参构造
//super();//3、目前父类没有无参构造了,会报错
super(8);//4、此时我们只能调用父类的含参构造
System.out.println("Sub...无参构造方法");
}
}
注意:
构造方法不能被继承
拓展
1、this和super的区别
1.this代表本类对象的引用,super代码父类对象的引用
2.this用于区分局部变量和成员变量;
3.super用于区分本类变量和父类变量
4.this成员变量this成员变量()this(参数),代表调用本类的内容;
5.super成员变量super.成员方法()super(参数),代表调用父类内容
6.this和super不可以同时出现在用一个构造方法里,他们两个只要出现都得放在第一行,同时出现的话,到底第一行放谁呢?
2、重写与重载的区别(overload和override的区别)
1.重载:是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,及参数的数量和参数类型不能完全相同;
2.重写:是存在子父类之间的,子类定义的方法与父类定义的方法具有相同的方法名字,相同的参数列表和相同的返回值类型
3.重写时父类与子类之间多态性的一种表现;
4.重载是一种多态性的一种表现
十一static
1、概念
是java中的一个关键字
用于修饰成员(成员变量和成员方法)
2、特点
1.可以修饰成员变量,成员方法;
2.随着类的加载而加载,优先于对象加载;
3.只加载一次机会一直存在不在开辟新的空间;
4.全局共享,可以被多个对象共享;
5.可以直接被类名调用;
6.静态只能调静态,而非静态可以随意调用
7.static不能和this和super公用,因为有static时可能还没有对象
3、入门案例
package cn.tedu.staticdemo;
//测试 静态 入门案例
public class Test_Static {
public static void main(String[] args) {
//测试
//2、静态资源,优先于对象加载
StaticDemo.game();//3、静态资源,可以直接被类名调用
StaticDemo demo = new StaticDemo();
demo.show();
System.out.println(demo.a);
//4、全局共享,可以被多个对象共享
demo.name = "jack";
StaticDemo demo2 = new StaticDemo();
System.out.println(demo2.name);//已经看到了demo对象修改之后的效果了,确实是共享数据,不然不会看到
System.out.println(StaticDemo.name);
}
}
//创建类
class StaticDemo {
//提供静态资源
//1、static可以修饰成员变量、成员方法
static String name;
static public void game() {
System.out.println("game()...");
}
//提供普通资源
int a = 10;
public void show() {
System.out.println("show()...");
}
}
静态方法内存图
静态调用关系
只是为了测试调用之间的关系,没有输出语句,如果console空白,不要惊讶!!!
package cn.tedu.staticdemo;
//测试静态的调用关系
public class Test_Static2 {
public static void main(String[] args) {
}
}
class StaticDemo2{
//提供普通资源
int age = 10;
public void game() {
//1、普通资源调用静态资源? --可以
show();
System.out.println(name);
System.out.println("game()...");
}
//提供静态资源
static String name;
static public void show() {
//2、静态资源调用普通资源? --不可以,原因:静态只能调用静态,使用的局限性强
//报错信息:Cannot make a static reference to the non-static method game() from the type StaticDemo2
//game();
//System.out.println(age);
System.out.println("下象棋....");
}
}
总结
1.静态资源只能掉静态
2.普通资源可以随意调用
4、静态代码块
对着类加载而加载,并且之被加载一次,一般用于项目有初始化或者加载资源
4.1概述
静态代码块:在类加载时被加载,并且只被加载一次,一般用于项目初始化
构造代码块:在调用构造方法前会被自动调用,每次创建对象都会被调用;
局部代码块:方法里的代码块,方法被调用时才会执行;
静态代码块:static()
位置:在类里方法外;
TODO创建测试类:类中写好静态代码块,构造代码块,构造方法,普通方法里嵌套局部代码块。测试他们呢的执行顺序;
静态-构造代码块-构造方法-局部
测试静态代码块
package cn.tedu.staticdemo;
//测试静态代码块
public class Test_StaticBlock {
public static void main(String[] args) {
//创建对象测试
StaticDeom3 s = new StaticDeom3();
StaticDeom3 s2 = new StaticDeom3();
StaticDeom3 s3 = new StaticDeom3();
}
}
class StaticDeom3{
//位置:是在类里方法外
//加载时机:早于对象,是随着类的加载而加载的,而且只会被加载一次来提高效率
//常用来完成项目的启动或者加载资源
static {
System.out.println("静态代码块");
}
//构造代码块
{
System.out.println("构造代码块");
}
//构造方法
public StaticDeom3() {
System.out.println("构造方法");
}
}```
控制台显示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201208201344957.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTQ3MzgzNA==,size_16,color_FFFFFF,t_70)
##### 静态变量和实例变量的区别
在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加;
在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
【下篇预告】
final
多态
异常
.......