1回顾
1.1面向对象和面向过程
面向对象:面对一个问题(老曹开车去重庆),考虑需要多少对象,在考虑每个对象有哪些方法(行为)和属性(特征),最后考虑对象之间如何协作
面向过程:面对一个问题,考虑分步骤去解决,不去考虑对象的存在。
面向过程用于开发简单的程序
汇编、C语言为代表
手机卡充值、电脑的驱动
面向过程不会被淘汰。
面向对象用于企业软件开发,通常用于复杂的业务逻辑
1.2定义类
1.3创建对象
1.4调用方法
//作业:定义一个学生类型 name no age eat() study()
package com.whsxt.day2.homework;
public class Student {
String name;
/**
* 学号
*/
String no;
public void eat(){
System.out.println(name+"吃饭.....");
}
public void study(){
//先吃饭再学习,在study()方法里面调用eat()方法
eat();
System.out.println(name+"正在学习,学号是:"+no);
}
}
package com.whsxt.day2.homework;
/**
* @author caojie
* 在学校可以创建学生
* 学校有学生
*/
public class School {
public static void main(String[] args) {
//new Student() 表示创建了一个Student类型的对象
// tom 接收创建的对象 tom理解为Student类型对象的代言人
// tom操作Student类型的对象
Student tom = new Student();
tom.name="Tom";
tom.no="FK01243224";
tom.study();
}
}
2类和对象
2.1构造方法
2.1.1概念
使用new关键字调用的方法叫做构造方法,通常在工作中用于创建对象
例如: new Scanner(System.in); //创建扫描器对象
new Student(); 创建学生对象
Student tom = new Student();
2.1.2特征
1 构造方法的名称必须跟类同名
2 构造方法没有返回值
3 如果一个类没有定义构造方法,那么在执行过程中,JVM会为其分配一个默认构造方法
2.1.3作用
唯一的职责:创建对象,为对象的属性赋值(为对象的属性初始化)
2.1.4解决哪些问题
使用构造方法完成属性的赋值(初始化)
package com.whsxt.day2.oop1;
public class Student {
String name;
int age;
String no;
/**
* 爱好
*/
String hobby;
/**
定义构造方法,在构造方法体内部为属性赋值
将局部变量的值赋给成员变量
例如: 局部变量stuName的值赋给成员变量name
*/
Student(String stuName,int stuAge,String stuNo,String stuHobby){
name = stuName;
age = stuAge;
no = stuNo;
hobby = stuHobby;
}
public void study(){
//成员方法执行的时候,所有的属性都被构造方法初始化了(赋初始值)
System.out.println(name+"正在学习,学号是:"+no+"年龄是:"+age);
System.out.println("学习完毕"+hobby);
}
}
package com.whsxt.day2.oop1;
public class School {
public static void main(String[] args) {
//Student tom = new Student();
//直接为属性赋值存在确定:赋值麻烦,容易出现漏写
//如何解决:将属性赋值的过程交给构造方法来完成
// tom.age=18;
// tom.hobby="Football";
// tom.no="AF10011";
// tom.study();
//调用构造方法创建对象
Student tomson = new Student("Tomson", 18, "AF010101", "Football");
//调用成员方法
tomson.study();
}
}
小结:1构造方法用于确保对象属性的完整性(初始化对象的属性)
2 此时成员方法调用之前所有的属性都会妥善初始化
2.2this关键字
概念:this表示当前使用new关键字创建的对象
工作中那些地方会用到this关键字:
1当成员变量(属性)和局部变量(参数)名称相同,使用this区分
package com.whsxt.day2.oop2;
public class Student {
String stuName;
int stuAge;
String stuNo;
String stuHobby;
/**
定义构造方法,在构造方法体内部为属性赋值
将局部变量的值赋给成员变量
例如: 局部变量stuName的值赋给成员变量name
*/
Student(String stuName,int stuAge,String stuNo,String stuHobby){
//局部变量的值赋给局部变量(自己)
//stuName = stuName;
//此时this.stuName表示当前对象的成员变量(stuName)
this.stuName = stuName;
this.stuAge = stuAge;
this.stuNo = stuNo;
this.stuHobby=stuHobby;
}
public void study(){
//String stuHobby="Basketball";
//成员方法执行的时候,所有的属性都被构造方法初始化了(赋初始值)
System.out.println(stuName+"正在学习,学号是:"+stuNo+"年龄是:"+stuAge);
System.out.println("学习完毕"+this.stuHobby);
}
}
2 一个构造方法里面调用另外一个构造方法
package com.whsxt.day2.oop2;
public class Student {
String stuName;
int stuAge;
String stuNo;
String stuHobby;
/**
定义构造方法,在构造方法体内部为属性赋值
将局部变量的值赋给成员变量
例如: 局部变量stuName的值赋给成员变量name
*/
Student(String stuName,int stuAge,String stuNo,String stuHobby){
this.stuName = stuName;
this.stuAge = stuAge;
this.stuNo = stuNo;
this.stuHobby=stuHobby;
}
Student(){
//在无参构造方法中调用有参构造方法 默认的名称、年龄、学号、爱好
//编译错误:一个构造方法调用另一个构造方法必须位于第一行
//System.out.println("Start");
//一个构造方法调用另一个构造方法的操作只能一次
//this("Jerry");
this("Stone", 20, "ABCDEFG", "Swimming");
}
Student(String stuName){
}
public void study(){
//String stuHobby="Basketball";
//成员方法执行的时候,所有的属性都被构造方法初始化了(赋初始值)
System.out.println(stuName+"正在学习,学号是:"+stuNo+"年龄是:"+stuAge);
System.out.println("学习完毕"+this.stuHobby);
}
}
package com.whsxt.day2.oop2;
public class School {
public static void main(String[] args) {
//使用无参数构造方法创建对象
Student tomson = new Student();
tomson.study();
}
}
小结:如果一个类没有构造方法,会分配一个默认无参构造方法,如果有构造方法,再也不会分配默认构造方法了
3面向对象特征之封装
封装、继承、多态
Java为什么是面向对象的语言?因为Java支持面向对象的特征封装、继承、多态,所以是面向对象语言。
封装的概念:如果你不想让某些数据被外界访问,那么将数据隐藏
如果你想让某些数据对外公开,可以将数据公开。
3.1属性的封装
为什么需要对属性进行封装?
直接为属性赋值,缺点是不可控,因为:你无法判断属性的名称是否为空,无法判断邮箱是否合法。
如何为属性进行封装呢?
将属性私有化,然后为属性提供setXXX方法和getXXX方法,通过调用setXXX方法为属性赋值,调用getXXX()方法获取(读取)属性的值。
好处:你在调用setXXX方法为属性赋值之前可以验证有效性,从而可以控制属性赋值的正确性。
如何操作?
package com.whsxt.day2.oop3;
public class Student {
/**
*封装 属性私有化,外界不能直接访问我的私有属性
*/
private String name;
/**
* 为属性赋值
* @param name 学生姓名
*/
public void setName(String name){
//条件成立:表示参数name为空,为其产生一个默认名称
if(null == name || name.length()==0){
this.name="Stone";
}else{
this.name = name;
}
}
public String getName(){
return name;
}
public void study(){
System.out.println(name+"正在学习");
}
}
package com.whsxt.day2.oop3;
public class School {
public static void main(String[] args) {
Student stu = new Student();
//stu.name ="Tom";
//stu.name= null;
//为属性赋值
stu.setName(null);
//调用Student对象的getName()方法获取名称
String stuName = stu.getName();
System.out.println("stuName="+stuName);
//编译错误:The field Student.name is not visible
//name属性不能访问(不是有效的)
//stu.name="Sam";
}
}
小结:属性封装的核心private关键字
private私有化, 请不要碰我(除了定义属性的类本身,其它任何地方都不能访问)
属性私有化,但是可以提供setXXX()方法设置属性的值,set开头的方法是变异器(值可以改变的),例如name=null;------------》name="Stone"
该可以提供getXXX()方法访问属性值,get开头的方法访问器(外界调用get方法获取属性值)
setXXX():写操作 (改变属性值)
getXXX():读操作(获取属性值)
作业:定义动物类,属性和行为自己定义
1 练习构造方法
2 练习this关键字
3 练习封装
3.2方法的封装
隐藏实现细节
场景:输入一个年份,判断是否是闰年
特征:输入一个数字,得到一个结果。如何判断闰年,我向外界隐藏
package com.whsxt.day2.oop4;
/**
* @author caojie
* 方法的封装
* Leap有一个方法judgeLeap()用来判断某个年份是否为闰年,判断的细节对外界隐藏
* 只提供方法给外界调用(隐藏了实现细节)
*/
public class Leap {
private int year;
public void setYear(int year){
this.year = year;
}
public int getYear(){
return year;
}
public Leap(int year){
this.year = year;
}
/**
* 判断年份是否为闰年
* @return true 是闰年,false不是闰年
*/
public boolean judgeLeap(){
return year%4==0 && year%100!=0 || year%400==0;
}
}
package com.whsxt.day2.oop4;
import java.util.Scanner;
/**
* @author caojie
* 验证方法的封装
* 客户使用Leap类型完成闰年的验证
*/
public class Test {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入年份");
int year = input.nextInt();
Leap leap = new Leap(year);
//判断闰年的细节(如何判断),向客户隐藏
boolean result = leap.judgeLeap();
String rs = result?"闰年":"不是闰年";
System.out.println(year+rs);
}
}
3.3类的封装
具有相同属性(特征)和行为的一组对象,将其封装成一个类
场景:定义一个动物类,属性和行为自定义
package com.whsxt.day2.oop5;
/**
* @author caojie
* 具有相同属性(特征)和行为的一组对象,将其封装成一个类
* 例如:小黑、小白、小花 都是Animal
* 所有的动物都有 昵称
* 所有的动物都有 吃饭的行为
*/
public class Animal {
/**
* 动物的昵称
* Alt+S --->Generic Getters/Setters 自动生成Get/Set
*/
private String nikeName;
public String getNikeName() {
return nikeName;
}
public void setNikeName(String nikeName) {
this.nikeName = nikeName;
}
public Animal(String nikeName) {
this.nikeName = nikeName;
}
public Animal() {
this("小黑");
}
/**
* 所有的动物都具备吃饭的行为
* @param food 食物
*/
public void eat(String food){
System.out.println(nikeName+"正在吃"+food);
}
}
package com.whsxt.day2.oop5;
/**
* @author caojie
*动物园管理员:产生一个或者一组对象
*/
public class Zookeeper {
public static void main(String[] args) {
Animal xiaoHei = new Animal();
xiaoHei.eat("骨头");
}
}
3.4构造方法的封装
如果你想让构造方法给外界使用,将其定义为公有
如果你不想让构造方法给外界使用,其定义为私有
如果你只想让构造方法在包的内部使用,将其定义为friendly (什么都不写)
Student(){}
package com.whsxt.day2.oop6;
public class Danta {
private String color;
/**
* 公有化的构造方法,任何地方都能访问,本类、同一包下、包外部都可以访问(创建对象)
* @param color
*/
// public Danta(String color){
// this.color = color;
// }
/**
* 没有任何访问修饰符是friendly,只能在本类和包内部
*/
// Danta(String color){
// this.color = color;
// }
/**
* 构造方法私有化,自己可以访问自己:除了本类其它任何地方都不能访问
*/
private static Danta danta = new Danta("Yellow");
private Danta(String color){
this.color = color;
}
/**
* 定义一个公有的静态的方法,返回唯一Danta对象
*/
public static Danta getDanta(){
return danta;
}
}
package com.whsxt.day2.oop7;
import com.whsxt.day2.oop6.Danta;
public class KFC2 {
public static void main(String[] args) {
//在包外也可以创建Danta对象
//不能再包外部访问friendly构造方法
//new Danta("Yellow");
//调用Danta的公有的静态的方法,获取Danta对象
Danta danta = Danta.getDanta();
System.out.println(danta);
}
}
小结:1和对象之间的联系?
类是对象的一个抽象表示,一个类可以创建多个对象
对象是类(Type or Class)的一个实例, 猫、狗都是动物类型的一个实例
2封装:隐藏数据
private 除了类本身,其它任何地方都不能访问
public 任何地方都能访问
3对象之间的一个关系
学生有车
package com.whsxt.day2.oop8;
public class Car {
/**
* 车有品牌
*/
private String brand;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Car() {
}
public Car(String brand) {
this.brand = brand;
}
public void start(){
System.out.println(brand+"启动");
}
public void stop(){
System.out.println(brand+"停车");
}
public void speed(){
System.out.println(brand+"加速");
}
}
package com.whsxt.day2.oop8;
public class Student {
private String name;
/**
* 学生有车
*/
private Car car;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public Student(String name, Car car) {
this.name = name;
this.car = car;
}
public Student() {
}
public void driver(){
//有车对象才能驾驶
if(null != car){
car.start();
car.speed();
car.stop();
}else{
System.out.println(name+"不具备驾驶行为");
}
}
}
package com.whsxt.day2.oop8;
public class School {
public static void main(String[] args) {
//创建一个车对象:benz
Car benz = new Car("Benz");
//创建学生对象 将Car对象benz注入到Student中
Student sam = new Student("Tom", benz);
sam.driver();
}
}
作业:练习对象之间的关系
房子有窗户
电脑有鼠标
4面向对象特征之继承
4.1生活中的继承
父和子的关系,父在上,子在下
4.2程序中的继承
继承的语法:
public 子类 extends 父类{
}
extends: 扩展、延伸(子类是父类的一个延伸)
子类可以使用父类的非私有属性和行为
场景:学生是人
人是父类:有eat()方法
学生是子类:有name属性,有eat()方法和study()方法
package com.whsxt.day2.oop9;
/**
* @author caojie
* Person 是一个父类,所有的Person都有吃饭的行为
*/
public class Person {
public void eat(){
System.out.println("吃饭");
}
}
package com.whsxt.day2.oop9;
/**
* @author caojie
* 学生继承人类
*/
public class Student extends Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String name) {
this.name = name;
}
public Student() {
}
public void study(){
System.out.print(name);
//因为子类继承于父类,所以子类可以使用父类的非私有行为(方法)
eat();
System.out.println("study");
}
}
测试类
package com.whsxt.day2.oop9;
public class School {
public static void main(String[] args) {
Student tom = new Student();
tom.setName("Tom");
tom.study();
}
}
4.3super关键字
this当前对象
super当前对象的父对象
作业:人有姓名和年龄,会吃饭和走路
学生是人有学号,能够学习
动物有颜色、性别属性,会吃饭、会跑
猫是一种动物,有昵称属性,会爬树
4.4继承中的构造方法
4.5访问权限
4.6方法覆盖
4.7final关键字