目录
2.4.6向下转型会出现的异常:ClassCastException(类型不匹配)
2.5.2.如果子父类中的成员变量名称一致的访问情况,结果是什么?
1.面向对象
1.1面向对象的思想
- 面向对象更符合生活中的思想习惯
- 角色改变了,让我们从执行者变为指挥者
- 让复杂的事物简单化
举例:洗衣服
面向过程:把衣服脱下--找一个盆--放点洗衣粉--加点水--把衣服扔进去--搓一搓--清洗衣服--拧干--晾起来
面向对象:把衣服脱下--打开全自动洗衣机--扔进去--一键即可--晾起来
1.2什么是对象
- 一切客观从在的事物都是对象,万物皆对象
- 任何对象,一定具有自己的特征和行为
对象的特征:称为属性,代表了对象有什么。
对象的行为:称为方法,代表了对象会什么,能做什么。
- 例:手机
属性:有品牌,颜色,价格……
方法:聊微信,打电话,打游戏……
1.3程序中的对象
程序模拟现实世界,就必须有现实世界中对应的对象
现实世界中的对象多数来自模板,程序中的对象也应该有模板----类。
- 程序中的模板就称为类
1.4类
1.4.1类的抽取和定义
在一组相同或类似的对象中,抽取出共性的特征和行为,保留所关注的部分
例:狗:有不同的种类:哈士奇,藏獒,贵宾犬,牧羊犬等等
共有的属性:品种、年龄、性别、毛色……
共有的方法:吃、睡……
将这些共有的属性和方法写在同一个类中就有了一个基础的狗的模板----即狗类
public class Dog { //特征----属性 String breed ; //品种 int age ; //年龄 String sex ; //性别 String forColor;//毛色 //行为---方法 public void eat() { System.out.println("狗吃..."); } public void sleep() { System.out.println("狗睡觉..."); } }
1.4.2对象的创建
定义了类之后如何使用类-----创建对象
创建对象的格式: 类名 对象名 = new 类名();
例:
class DogTest{ public static void main(String[] args) { //创建一个狗类对象----即给出一个具体的狗 Dog dog = new Dog(); //用创建好的对象给类中的属性赋值 dog.breed = "二哈"; dog.age = 3; dog.sex = "公"; dog.forColor = "白色"; //用创建好的对象调用方法模拟现实中狗的行为 dog.eat(); dog.sleep(); } }
类:定义类对象应具有的特征和行为,类是对象的模板。
即:类是现实中相同或相似事物的概括。
对象:拥有多个特征和行为的实体,对象是类的实例。
即:对象是现实中存在的个体------如XXX家养的狗----是确实具体存在的一个可以被感知的
1.4.3类中的变量----实例变量和局部变量的区别
实例变量:又称特征、属性、成员变量
实例变量和局部变量的区别
1)书写位置不同
- 局部变量:在方法定义中或者方法声明上
- 成员变量:在类中,方法外定义的变量
2)内存中的位置不同
- 局部变量:是在栈内存中
- 成员变量:在堆内存中
3)生命周期不同
- 局部变量:随着方法调用而存在,随着方法调用完毕而消失
- 成员变量:随着对象的创建完毕而存在,随着对象被GC回收,而消失 (不是立即被回收,等待空闲时候回收!)
4)初始化不同
- 局部变量:要么先在赋值,要么直接赋值(在使用之前必须给局部变量赋值!)
- 成员变量:它可以不初始化(系统默认初始化)
1.5.方法总结
1.5.1实例方法
格式:
修饰符 放回值类型 方法名(形参列表){
方法的实现体
}
代码体现
//狗睡觉这一行为的方法书写 public void sleep() { System.out.println("狗睡觉..."); }
1.5.2方法的重载
重载(Overload):在一个类中定义对各相同名称的方法。
要求:
1)方法名相同
2)方法的参数列表不同(类型 、个数、顺序)
3)与访问修饰符、返回值类型无关
好处:灵活、方便、屏蔽使用差异。
代码体现
//求和方法 //求两个数的和 public int add(int a,int b) { return a+b; } //求三个数的和 public int add(int a,int b,int c) { return a+b+c; } //求四个数的和 public int add(int a,int b,int c,int d) { return a+b+c+d; }
1.5.3构造方法
1.构造方法:类中特殊的方法,主要用于创建对象。
2.特点:
- 名称与类名完全相同。
- 没有返回值类型
- 创建对象时,触发构造方法调用,不可同过语句手动调用
3.分类
- 有参构造方法:可以对类的属性进行初始化
- 无参构造方法:再没有手动添加构造方法时系统会默认添加无参构造方法,如果有有参构造方法那么系统就不会自动添加无参构造方法了,所以自己最好将无参构造方法手动添加上。
4.作用:给当前类对象成员变量进行数据的初始化!
代码体现
public class Dog { //属性 String breed ; int age ; String sex ; String forColor; //无参构造方法 public Dog() { } //有参构造方法 public Dog(String breed, int age, String sex, String forColor) { this.breed = breed; this.age = age; this.sex = sex; this.forColor = forColor; } //实例方法/成员方法 public void eat() { System.out.println("狗吃..."); } public void sleep() { System.out.println("狗睡觉..."); } }
1.5.4抽象方法
1.抽象方法:是某个功能或行为的一个声明,没有方法实现(所以必须要进行方法重写)
2..格式:
返回值类型 方法名(); 隐藏了修饰符,public 、abstract
代码体现
//接口 public interface Person { //抽象方法 void setData(); String getData(); } //抽象类 abstract class Persons{ //抽象方法 void eat(); void sleep(); }
3.应用场景
通常用于接口和抽象类中
4.要求:
抽象方法必须要有子类或子实现类来重写
1.5.5方法重写(方法覆盖)
1.方法重写:在继承关系下的子类中出现了和父类一模一样的方法,称为方法重写
2.方法重写的要求:要有继承关系
3.方法重写的原则:方法名、参数列表、返回值类型必须和父类相同
访问修饰符可与父类相同或是比父类更宽泛
4.方法重写后执行:调用时优先执行子类重写后的方法
代码体现:
//接口 public interface Person { //接口中的方法定义 void setData(); } //抽象类 abstract class Staff{ //抽象类的方法定义 public abstract void show(); } //子实现类---用来继承抽象类的抽象方法和接口的抽象方法 class Teacher extends Staff implements Person{ //接口抽象方法的重写 @Override public void setData() { System.out.println("这是接口的抽象方法的重写"); } //抽象类的抽象方法的重写 @Override public void show() { // TODO Auto-generated method stub } }
2.面向对象的三大特征
2.1三大特征是什么
1.封装:尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限。
理解:就是将类中的属性私有化(private),使外界不能直接访问,并对外部提供公共的访问方法setXxx()/getXxx()。
2.继承:类与类之间的一种赠与和获得
理解:就是将一个类看作父类,另一个类看作子类,父类中的属性,方法(没有final修饰的)都可以在子类中使用,即父类有的子类都有,子类有的父类不一定有。
3.多态:父类的引用指向子类,从而产生多种形态。
理解:由于信息的不全面,使结果不能唯一。例:xxx是动物,由于信息的不全面,动物有很多,xxx具体是什么我们是不知道的,但是我们会得出很多的答案xxx=狗、xxx=猫……
2.2封装的相关内容
2.2.1封装的概念和理解
概念:尽可能隐藏对象的内部实现细节,控制对象的修改及访问的权限。
理解:就是将类中的属性私有化(private),使外界不能直接访问,并对外部提供公共的访问方法setXxx()/getXxx()。
2.2.2封装的必要性
在对象的外部,为对象的属性赋值,可能存在非法数据的录入,为了对属性的赋值加以控制,就有了封装。
2.2.3封装的相关代码
代码体现
public abstract class Role { //属性的私有化----封装:外界不可直接访问 private String name ; private int age ; private String sex ; //提供公共的访问方法 //setXxx()赋值 //getXxx()获取值 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
外界访问格式:
1)创建属性所在类的对象-----:类名 对象名 = new 类名();
2)使用对象访问格式:
对象名.setXxx(赋值);
对象名.getXxx(取值);
代码体现
//一般将有main函数的类称为测试类 public class Person { public static void main(String[] args) { //创建一个Student对象 Student stu = new Student(); //给对象属性赋值 stu.setName("李小白"); stu.setAge(25); stu.setSex("男"); //将对象的值输出 System.out.println("我叫"+stu.getName()+"性别"+stu.getSex()+"今年"+stu.getAge()+"岁了"); } } //学生类 class Student { //属性的私有化----封装:外界不可直接访问 private String name ; private int age ; private String sex ; //提供公共的访问方法 //setXxx()赋值 //getXxx()获取值 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
输出的结果就是:我叫李小白性别男今年25岁了
2.3继承的相关内容
2.3.1什么是继承
- 继承:类与类之间的一种赠与和获得
- 理解:就是将一个类看作父类,另一个类看作子类,父类中的属性,方法(没有final修饰的)都可以在子类中使用,即父类有的子类都有,子类有的父类不一定有。
- 格式:
class 子类名 extends 父类名{}
- 应用:产生继承关系后,子类可以使用父类中的属性和方法也可以定义子类自己的特有属性和方法
2.3.2继承的特点
Java中类与类之间是单继承,一个类只能有一个直接父类,但可以多层继承
2.3.3继承的好处:
1)提高了代码的复用性
2)提高了代码的维护性
3)是多态的前提条件
2.3.4不可被继承的
构造方法:类中的构造方法,只负责创建对象不可被继承
private修饰的属性和方法:被修饰的成员尽本类可见
父子类不在同一个包中的默认修饰符修饰的成员:尽同包可见
2.3.5继承的相关代码
继承的格式代码
//父类 public class Animal { } //子类 class Dog extends Animal{ }
继承的相关内容的调用代码
定义的父类
//父类 public class Animal { private String name ; private int age ; private String sex ; public Animal() { super(); // TODO Auto-generated constructor stub } public Animal(String name, int age, String sex) { super(); this.name = name; this.age = age; this.sex = sex; } 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public void eat() { System.out.println("动物吃..."); } }
继承父类的子类
//子类 public class Dog extends Animal{ public Dog() { super(); // TODO Auto-generated constructor stub } public Dog(String name, int age, String sex) { super(name, age, sex); } //方法的重写 public void eat() { System.out.println("狗在吃..."); } //输出信息的方法 public String toString() { return "有一只叫" + getName() + getAge() + "岁的" + getSex() + "狗"; } }
测试代码的类
public class Test { public static void main(String[] args) { //有参构造赋值,在创建对象时为对象的属性初始化 Dog dog = new Dog("狗子",2,"公"); System.out.println(dog.toString()); dog.eat(); } }
结果是
2.4多态的相关内容
2.4.1什么是多态
多态:一个事物在不同时刻体现的不同状态(堆内存中的变化)
多态在创建对象时的格式
父类名 对象名 = new 子类名();
此方法创建的对象只能调用子类中继承于父类的属性和方法,不能调用子类特有的属性和方法
2.4.2多态的前提条件
1)必须有继承关系
2)存在方法重写
3)父类引用指向子类对象
Fu f = new Zi();
2.4.3多态的访问特点
- 成员变量:编译看左,运行看左边
- 成员方法:(非静态的成员方法):编译看左,运行看右边:存在方法重写
- 静态的方法:编译看左,运行看左边(静态算不上方法重写,直接跟类相关的!)
- 构造方法:由于存在继承关系,还需要分层初始化(构造方法目的:对数据进行初始化!)
2.4.4多态示例
多态示例代码
//测试类 public class DuotaiTest { public static void main(String[] args) { //向上转型----装箱 Animal a = new Cat(); Animal b = new Dog(); AnimalTool.userAnimal(a); AnimalTool.userAnimal(b); } } //工具类 class AnimalTool{ public static void userAnimal(Animal a) { System.out.print("我养一只"); a.eat(); a.sleep(); } } //动物类-----父类 class Animal{ public void eat() { System.out.println("动物吃..."); } public void sleep() { System.out.println("动物睡..."); } } //狗子---子类 class Dog extends Animal{ public void eat() { System.out.println("狗子吃..."); } public void sleep() { System.out.println("狗子睡..."); } } //猫儿-----子类 class Cat extends Animal{ public void eat() { System.out.println("猫儿吃..."); } public void sleep() { System.out.println("猫儿睡..."); } }
结果
2.4.5多态的应用
场景一
使用父类作为方法形式参数实现多态,使方法参数类型更为宽泛。(示例见2.4.4多态的示例)
是类型转换的向上转型------装箱
场景二
使用父类作为方法返回值实现多态,使方法可以返回不同的子类对象。
向下转型------------拆箱
示例
public class DuotaiTest { public static void main(String[] args) { Animal a = new Cat();//向上转型 Cat cat = (Cat)a; //向下转型 //Cat cat = (Dog)a; //转换异常 不能将猫转换为狗 } }
2.4.6向下转型会出现的异常:ClassCastException(类型不匹配)
原因:运行时期异常(RuntimeException)的一种是使用向下转型的时候类型不匹配导致的!
解决方案:将数据类型改为一致
2.5 部分常用关键字和常见问题的总结
2.5.1 this关键字和super关键字的区别
- this:代表当前类对象的地址值引用
- super:代表父类的空间标识(理解为父类的对象的地址值引用)
- 访问区别
1)成员变量
this.变量名:当前类的成员变量
super.变量名:访问的父类的成员变量
2)成员方法
this.方法名:当前类的成员方法
super.方法名:父类的成员方法
3)无参构造方法
this():访问当前类的无参构造方法
super():访问父类的无参构造方法
4)有参构造方法
this(xx):访问当前类的有参构造方法
super(xx):访问父类的有参构造方法
2.5.2.如果子父类中的成员变量名称一致的访问情况,结果是什么?
遵循"就近原则":
- 1)先在子类的局部位置找,如果有就使用
- 2)如果没有,在子类的成员位置找,有就使用
- 3)如果没有,在父类的成员位置找,有就使用
- 4)如果父类没有,说明就没有这个变量,报错了!
2.5.3被final关键字修饰的成员的特点
final:状态修饰符,最终的,无法更改的!
- final修饰类,该类不能继承
- final修饰变量,该变量此时是一个常量!
- final修饰成员方法,该方法不能被重写!