能够定义类并创建对象
关键字:class
修饰符 class 类名{
成员变量
成员方法
构造方法
代码块
内部类
}
例如:
定义一个学生类,包含属性姓名,年龄
public class Student{
public String name;
public int age;
}
默认有一个无参构造方法
关键字:new
类名 对象名 = new 类名(参数);
例如:
创建学生对象
Student stu = new Student();
//给姓名赋值为小明
stu.name = "小明";
stu.age = 18;
System.out.println(stu.name);
类定义的关键字:class
对象定义的关键字:new
private关键字的含义就是私有。可以用来对成员进行封装
第一步:先把成变量使用private封装
第二步:提供getter、setter方法
举例:
定义一个学生类,含有属性姓名,年龄。对姓名和年龄进行封装,并提供可访问的getter、setter方法
public class Demo01 {
public static void main(String[] args) {
Student stu = new Student();
//给name属性赋值小明
//stu.name
stu.setName("小明");
//System.out.println(stu.name);
System.out.println(stu.getName());
}
}
/*
定义一个学生类,含有属性姓名,年龄。对姓名和年龄进行封装,并提供可访问的getter、setter方法
*/
class Student{
//1. 将成员变量使用private进行修饰
private String name;
private int age;
//2. 提供getter、setter方法
//name的getter和setter方法
//getter:获取成员变量值
public String getName() {
return name;
}
//setter:负责赋值
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
封装使用什么关键字?
private
封装的步骤?
第一步:先把成变量使用private封装
第二步:提供getter、setter方法
格式:
修饰符 类名 (形参){
给成员变量初始化值
}
特点:
作用:
定义一个学生类,含有属性姓名,年龄。对姓名和年龄进行封装,并提供可访问的getter、setter方法
同时提供无参构造方法,满参构造方法。
public class Demo01 {
public static void main(String[] args) {
//使用无参构造方法创建对象
Student stu = new Student();
stu.setName("昌老师");
stu.setAge(18);
System.out.println(stu.getName() + "::" + stu.getAge());
stu.study();
//使用满参构造方法创建对象
Student stu2 = new Student("苏群", 17);
System.out.println(stu2.getName() + "::" + stu2.getAge());
stu2.study();
}
}
//定义一个学生类,含有属性姓名,年龄。对姓名和年龄进行封装,并提供可访问的getter、setter方法
//同时提供无参构造方法,满参构造方法。
class Student {
//1.成员变量
private String name;
private int age;
//2.构造方法
// 无参构造方法,(如果写了其他非无参构造方法,就没有默认的无参了)
public Student() {
}
// 满参构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//3.getter/setter
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;
}
//4.行为方法
public void study() {
System.out.println(name + "正在认真的学习Java");
}
}
构造方法特点?
构造方法有什么作用?
this关键字就是为了解决局部变量和成员变量名字冲突的调用问题。
格式:
this.成员变量
例如:
//构造方法
public Student(String name,int age){
this.name=name;
this.age = age;
}
//setter
public void setName(String name){
this.name = name;
}
public class Demo01 {
public static void main(String[] args) {
Student stu = new Student("张三");
System.out.println("stu.name = " + stu.name);
System.out.println("stu=" + stu);//stu=_03this关键字.Student@6bf256fa
}
}
class Student {
public String name;
public Student(String name) {
//name = name;//没有设置成功,使用冲突的局部变量和成员变量,就近选择局部变量
this.name = name;
System.out.println("this=" + this);//this=_03this关键字.Student@6bf256fa
}
//实例方法自己验证:调用方法的对象就是方法内部的this对象
}
this关键字含义?
this在构造器中就是指当前创建的对象,如果在实例方法中就是调用方法的对象
this关键字有什么作用?
区分名字冲突的成员变量和局部变量。
有名对象:有对象名保存地址的对象
Student stu = new Student();
Scanner sc = new Scanner(System.in);
匿名对象:没有对象名的对象就是匿名对象
new Student();
new Scanner(System.in);
匿名对象的使用特点:只能使用一次,对象名可以怎么用,匿名对象也可以怎么用。
public class Demo01 {
public static void main(String[] args) {
//- 直接使用匿名对象调用方法
new Student().setName("张三");
new Student("少林").study();
//- 直接当做一个参数传给方法
showStudent(new Student("李四"));
//有名对象
Student stu = new Student("张三");
showStudent(stu);
}
public static void showStudent(Student stu) {
stu.study();
}
//- 直接当做返回值进行传递
public static Student getStudent() {
return new Student("王五");
}
}
class Student{
private String name;
public Student() {
}
public Student(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
System.out.println("调用了set方法");
this.name = name;
}
public void study() {
System.out.println(name+"正在认真的学习Java");
}
}
什么是匿名对象?
没有对象名的对象
匿名对象怎么用?
只能用一次,对象名可以怎么用,匿名对象也可以怎么用
理解继承的思想
能够使用关键字extends书写继承的代码
能够知道继承的好处
面向对象的特性:封装,继承,多态
设计类的过程中就可以去使用继承,可以提高代码的复用性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbUtVkOc-1616501047834)(imgs/image-20201028103456573.png)]
Java中如何完成类型的继承:需要借助关键字,extends,implements
今日讲extends,类继承类使用 extends。
class Fu { //父类,基类,超类
成员
}
class Zi extends Fu{ // 子类
}
表示Zi类继承了Fu类。
继承的思想?
比如A类继承了B类,A就可以拥有B中的属性成分。
继承的好处?
提高代码的复用性
继承使用的关键字?
extends
格式
class A{}
class B{}
A继承B
class A extends B{}
以继承的思想定义以下类型:
如果不用继承的思想定义类,发现有属性:姓名,年龄。行为:吃饭,睡觉,会重复定义。
使用继承的思想定义类:
public class Demo01 {
public static void main(String[] args) {
//3. 测试
//学生类:
Student stu = new Student();
stu.name = "张三";//name就是父类继承下来的
stu.eat();//来自父类的方法
stu.sleep();//来自父类的方法
//老师类:
Teacher t = new Teacher();
t.name = "昌老师";//来自父类的属性
t.salary = 100000;//来自本类
t.eat();//来自父类的方法
t.teaching();//来自本类的方法
}
}
//1. 抽取父类,人(属性:姓名,年龄 行为:吃饭,睡觉)
class Person { //父类
public String name;
public int age;
public void eat() {
System.out.println(name + "在吃饭饭!");
}
public void sleep() {
System.out.println(name + "在睡觉觉!");
}
}
//2. 然后再定义子类
class Student extends Person {
}
class Teacher extends Person {
//特有的属性
public int salary;//薪资
//特有的行为
public void teaching() {
System.out.println(name + "老师,在教书书!");
}
}
如何使用继承思想设计类?
在设计很多类的时候,可以将共性的属性或者行为抽取到父类中。
【代码测试】
class Fu{
public int age; //公共的
protected int height; //受保护的
int weight;// 包私有的
private String sex; //私有的
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
class Zi extends Fu{
public void show1() {
System.out.println(age);
System.out.println(height);
System.out.println(weight);
//System.out.println(sex);//不能访问父类私有成分
System.out.println(getSex());//可以借助getter、setter方法进行访问
}
}
在子类方法中访问:
位置 | 子类方法中局部变量 | 子类成员变量 | 父类成员变量 |
---|---|---|---|
访问 | 直接访问 | this.成员变量 | super.成员变量 |
代码示例:
public class Demo02 {
public static void main(String[] args) {
Cat cat = new Cat();
cat.show();
}
}
class Animal{
int age = 10;
}
class Cat extends Animal{
int age = 20;
public void show() {
int age = 30;
//要求,把所有age变量的值都打印出来
System.out.println(age);//30
System.out.println(this.age);//20
System.out.println(super.age); // 10
}
}
继承中子类访问父类成员变量的特点?
不能直接访问的成分,可以借助公共的getter,setter方法进行访问
如果方法中局部变量,本类成员变量,父类的成员变量名字有冲突?
局部变量:直接访问
本类成员变量:this.
父类成员变量:super.
访问特点和成员变量是一样的。
同包中:子类可以访问父类的public,protected,包私有修饰的方法
不同包:子类可以访问父类的public,protected,的方法
如果子类中定义声明了与父类一样的方法,优先访问子类的方法。
public class Demo01 {
public static void main(String[] args) {
//创建子类对象访问方法
Zi zi = new Zi();
zi.test1();
zi.test2();
zi.test3();
//zi.test4(); //同包中,私有的父类方法不能访问
//父类和子类方法相同
zi.test5();
}
}
class Fu {
public void test1() {
System.out.println("这是父类的public修饰的test1方法");
}
protected void test2() {
System.out.println("这是父类的protected修饰的test2方法");
}
void test3() {
System.out.println("这是父类的包私有修饰的test3方法");
}
private void test4() {
System.out.println("这是父类的private修饰的test4方法");
}
public void test5() {
System.out.println("来自父类的方法");
}
}
class Zi extends Fu {
public void test5() {
System.out.println("来自子类的方法");
}
}
继承中子类访问父类方法的特点?
同包中:public,protected,包私有修饰的成分可以访问
不同包:public,protected修饰的成分可以访问
继承中如果子类方法和父类方法相同了,子类对象调用该方法优先访问谁呢?
优先访问子类方法
当父类中方法继承到子类后,不满足子类需要的时候,子类就可以对这个方法进行覆盖,重写(Override)。
如何重写父类中的方法呢?
声明不变,重新实现。
修饰符 返回值类型 方法名 (参数列表)
修饰符 返回值类型 方法名 (参数列表){
方法体的逻辑重写
}
例如:
class Animal {
public void eat(){
System.out.println("吃东西");
}
}
class Cat extends Animal{
//重写eat方法
public void eat(){
System.out.println("猫吃鱼");
}
}
@Override :注解,表示该方法是重写的方法。
IDEA重写方法:
代码实例
public class Demo01 {
public static void main(String[] args) {
Cat c = new Cat();
c.eat();
}
}
class Animal {
public void eat() {
System.out.println("动物吃东西!");
}
public void sleep() {
}
}
class Cat extends Animal {
//直接写方法名,回车补全
/* @Override //注解:表示该方法是重写的方法
public void eat() {
super.eat();//调用父类的eat方法
System.out.println("猫吃鱼!!");
}*/
//Ctrl+O:快捷重写
@Override
public void eat() {
System.out.println("猫吃鱼!!");
}
@Override
public void sleep() {
super.sleep();
}
}
方法重写是发生在子父类之间的关系。
子类方法覆盖父类方法,必须要保证权限大于等于父类权限。
子类方法覆盖父类方法,返回值类型、函数名和参数列表都要一模一样。
返回值类型(子类返回值类型要小于等于父类返回值类型【不考虑基本数据类型】)
子类继承父类,子类范围更具体更小的,父类范围会更抽象更宽泛。父类型大于子类型。
平时重写方法时:声明不变
为什么要重写?
父类继承到子类的方法逻辑不满足子类需要时,子类可以进行重写。
如何重写?
声明不变,重新实现。
构造方法是不能冲父类继承到子类中的,但是可以在子类中借助super关键字进行访问。
如何借助super关键字调用父类的构造方法?
格式:
需要在子类构造方法中第一句位置,使用super调用
super() 调用父类的无参构造
super(参数) 调用父类的有参构造方法
特点:
super调用构造方法一次只能有一个。
父类的构造方法,总是在子类构造方法执行前,执行。
子类的构造方法,一定会先调用父类构造方法,如果没有显式使用super调用,默认会有super()
代码实践
public class Demo01 {
public static void main(String[] args) {
Student stu = new Student();
System.out.println("stu.name = " + stu.name);
//使用满参构造方法创建对象
Student stu2 = new Student("李四",20,1);
System.out.println("stu2.name = " + stu2.name);
System.out.println("stu2.age = " + stu2.age);
System.out.println("stu2.id = " + stu2.id);
}
}
class Person {
public String name;
public int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
class Student extends Person {
public int id;
public Student() {
//super();//如果没有写,默认会有
super("张三", 18);
}
//构建一个满参,包含本类的属性,父类的属性初始化
public Student(String name, int age,int id) {
super(name, age);
this.id=id;
}
}
如何调用父类的构造方法?
继承的特点有三个:
只支持单继承
class A {}
class B {}
class C extends A{}
class D extends A,B{} //不行,错误
允许一个父类有多个子类
class A{}
class B extends A{}
class C extends A{}
允许类多层继承
class A{} //如果一个类没有显式的继承一个类,默认会继承Object(上帝类)
class B extends A{}
class C extends B{}
class D extends C{}
继承也是具有传递性的,A中的成分不仅会继承给B,也会继承给C,也会继承给D。
继承三个特点?
super和this都是指代的同一个对象,this表示的本类空间,super表示的父类空间。
this和super用法一样:
区别在于,this调用的是本类的成分,super调用父类的成分。
格式:
位置:必须在本类构造方法的第一句
this(参数)
注意:不能调用自身构造方法
特点:
代码实践:
public class Demo01 {
public static void main(String[] args) {
//使用无参构造方法创建对象,name和age都有初始的值
Student stu = new Student();
System.out.println("stu.name = " + stu.name);
System.out.println("stu.age = " + stu.age);
}
}
class Student {
public String name;
public int age;
public Student() {
//name : 尼古拉斯.赵四
//age : 18
//name = "尼古拉斯.赵四";
//age = 18;
this("尼古拉斯.赵四", 18);
}
public Student(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
super和this是的是什么?
只同一个对象的两个空间,super指父类空间,this指本类空间。
this如何调用本类其他构造方法?
位置:在本类的构造方法第一句
格式:this(参数)
不能调用自身,否则会报错。
this为何要调用本类其他构造方法?
abstract关键字:表示抽象。
使用关键字abstract修饰的类,称为抽象类。
使用关键字abstract修饰的方法,没有方法体,且以分号结尾的方法,称为抽象方法。
//抽象类
修饰符 abstract class 类名{
//抽象方法
修饰符 abstract 返回值类型 方法名(参数列表);
}
抽象类,抽象方法的使用场景。
抽取多个类的父类时,通常就会使用抽象类。如果多个类中有共同的方法,但是逻辑具体由不同,此时就可以使用抽象方法。
抽象类就是以父类的角色存在。
学生:姓名,年龄,吃饭,工作
老师:姓名,年龄,吃饭,工作
班主任:姓名,年龄,吃饭,工作
抽取父类人,描述上面的共同的父类。
分析:
属性:姓名,年龄
行为:吃饭,工作,吃饭大家都一样的,可以使用具体的方法,而工作,因为每个角色的内容不同,可以使用抽象方法。
public abstract class Person {
//属性
public String name;
public int age;
//构造方法
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//行为
public void eat() {
System.out.println("吃饭");
}
//抽象方法
public abstract void work();
}
什么叫抽象类,什么叫抽象方法?
被abstract修饰的类就是抽象类,被abstract修饰的方法就是抽象方法
抽象的关键字是什么?
abstract
什么时候可以使用抽象类,抽象方法?
抽取多个类的父类时,通常就会使用抽象类。如果多个类中有共同的方法,但是逻辑具体由不同,此时就可以使用抽象方法。
抽象类不能直接实例化对象使用。
可以定义子类继承抽象的父类,如果存在抽象方法,要将所有的抽象方法进行重写
重写抽象方法可以叫做实现。
如果子类不重写抽象方法,你可将子类也变成抽象类。
使用上一个知识点的Person抽象类作为父类定义学生类,老师类。
当我们使用一个类继承一个抽象类时,发现报错:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lIucYJa0-1616501047838)(imgs/image-20201028160114179.png)]
类Student必须要么定义成抽象类,要么把来自父类的抽象方法work实现
public class Demo01 {
public static void main(String[] args) {
//抽象类不能创建对象
//Person p1 = new Person();
//使用时,用其子类即可
Student stu = new Student();
stu.work();
stu.sleep();
}
}
//创建子类去继承抽象类,并实现抽象方法
class Student extends Person{
@Override
public void work() {
System.out.println("学生的工作,就是学习!!");
}
@Override
public void sleep() {
System.out.println("睡觉站着睡觉");
}
}
abstract class Teacher extends Person {
//父类的抽象方法就会继承到子类Teacher中。
}
抽象类怎么使用?
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
抽象类中,可以有构造器,是供子类创建对象时,初始化父类成员使用的。
理解:子类的构造方法中,有默认的super(),需要访问父类构造方法。
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
抽象类在抽取父类型的时候可以使用,有一些方法假如具体子类型有不同的逻辑,可以使用抽象方法。
抽象类的子类必须要实现所有的抽象方法。否则要变成抽象类。
对子类有一个约束,子类会根据父类而进行设计,体现一种模板思想。
抽象类可以当做父类型,里面定义抽象方法,可以约束子类一定要做一个具体的实现。
什么是设计模式?
设计模式体现的是解决一个问题一个需求的一种最佳实践。
模板设计模式:
可以利用抽象类定义一些需要子类完成的一系列功能的模板方法。子类继承抽象类之后,只要实现抽象方法。
而模板方法直接继承到子类,不需要重写。子类调用模板方法的时候,就可以按照模板的逻辑进行执行了。
例如:
我现在需要定义新司机和老司机类,新司机和老司机都有开车功能,开车的步骤都一样,只是驾驶时的姿势有点不同,
新司机:开门,点火,双手紧握方向盘,刹车,熄火
,老司机:开门,点火,右手握方向盘左手抽烟,刹车,熄火
。
使用模板设计模式进行定义相关的类,步骤:
抽象父类(模板)
//新司机:开门,点火,双手紧握方向盘,刹车,熄火,老司机:开门,点火,右手握方向盘左手抽烟,刹车,熄火。
abstract class Driver {
//定义方法
public void open() {
System.out.println("开门");
}
public void start() {
System.out.println("开火启动");
}
public abstract void zishi();
public void breakDown() {
System.out.println("刹车");
}
public void stop() {
System.out.println("熄火");
}
//模板方法:定义流程
public final void drive() {//final加上的目的就是为了阻断重写
open();
start();
zishi();
breakDown();
stop();
}
}
测试类及其子类:
public class Demo01 {
public static void main(String[] args) {
NewDriver d1 = new NewDriver();
d1.drive();//调用模板方法
System.out.println("=============");
OldDriver oldDriver = new OldDriver();
oldDriver.drive();//调用模板方法
}
}
class OldDriver extends Driver {
@Override
public void zishi() {
System.out.println("左手抽烟,右手搭在方向盘");
}
}
class NewDriver extends Driver {
@Override
public void zishi() {
System.out.println("双手握紧方向盘,聚精会神");
}
}
什么时候使用模板设计模式?
当子类都有一个固定的业务流程时,就可以使用模板设计模式
如何设计?
能够写出类的继承格式
使用extends关键字。
class A{}
class B extends A{}
能够说出类继承的三个特点
单继承
一个父类可以有多个子类
可以多层继承,有传递性
能够说出继承中子类访问成员的特点
子类和父类在同包:被public,protected,包私有修饰的的成员,子类可以访问
子类和父类在不同包::被public,protected 修饰的的成员,子类可以访问
如果子类定义了与父类一样的成员,优先访问子类的。
能够说出继承中方法重写的使用场景
当父类的方法继承到子类其逻辑不能满足子类需要时,就可以进行重写
能够说出this和super的使用方式及其区别
使用方式:
区别:
this访问本类,super访问父类
能够定义抽象类和抽象方法
abstract:表示抽象
abstract class 类名{
public abstract void test();
}
能够使用含有抽象方法的抽象类
能够说出父类抽象方法的存在意义
System.out.println(“熄火”);
}
//模板方法:定义流程
public final void drive() {//final加上的目的就是为了阻断重写
open();
start();
zishi();
breakDown();
stop();
}
}
测试类及其子类:
```java
public class Demo01 {
public static void main(String[] args) {
NewDriver d1 = new NewDriver();
d1.drive();//调用模板方法
System.out.println("=============");
OldDriver oldDriver = new OldDriver();
oldDriver.drive();//调用模板方法
}
}
class OldDriver extends Driver {
@Override
public void zishi() {
System.out.println("左手抽烟,右手搭在方向盘");
}
}
class NewDriver extends Driver {
@Override
public void zishi() {
System.out.println("双手握紧方向盘,聚精会神");
}
}
什么时候使用模板设计模式?
当子类都有一个固定的业务流程时,就可以使用模板设计模式
如何设计?