java入门第三节
一.什么是oop
1.pop与oop
(1).面向过程编程:(POP:Procedure Oriented Programming)
1.步骤清晰简单,第一步做什么,第二步做什么,按照顺序;
2.代码线性,严格按着顺序,侧重解决步骤
3.适合处理一些简单的问题
(2).面向对象编程:(OOP:Object Oriented Programming)
1.物以类聚,分类的思维方式,首先站在更高的层次看待事物,解决那些问题需要分类,然后对这些分类进行单独思考并规划和设计,最后才对某个分类下的细节进行面向过程的思考;(如.制定学习计划,先分科目,如英语,数学,再对每个科目怎么学进行思考,最后按计划依次执行)
2.明确目标,对象就是目标,目标就是对象
3.面向对象适合处理一些复杂的问题,适合处理多人协作的问题;(如.学校里面有很多老师,每个老师教的课程是不一样的,所有进行了分类,协作教育学生)
2.关于OOP的一些基本概念
(1).面向对象编程的本质:以类的方式组织代码,以对象的组织(封装)数据;
(2).三大特性:封装,继承,多态
(3).从认识论角度考虑是先有对象后有类。对象,是具体的事物(如.人)。类,是抽象的,是对对象的抽象(如.一个组织);
(4).从代码运行角度考虑是先有类后有对象,类是对象的模板;(如.印钞必须先有钞票的模板才能印钞)
3.类与对象的关系
Java 对象和类 | 菜鸟教程 (runoob.com)
(1).类:类是一种抽象的数据类型,它是对一类事物整体描述/定义,但是并不能代表一个具体的事物;(如.动物,手机,电脑,公司,等等)
(2).对象:对象是抽象的具体实例;
(3).实例:显示生活中的一个东西,对抽象的东西(对象)进行表示出来的产物,是一个活生生存在的事物,他是唯一的。对象 >= 实例;(如.张大爷家的狗,路上的一个行人)
(4).属性:类中的变量和方法总称为属性,属性包括共性与特性;
可以简单理解为类是一个模板,对象是一个具体的实例;
4.对抽象的理解
抽象是指将具体的事物抽象出来;
其实说白了,抽象---》抽出相同特征的对象(实例), 他和具体又是相对的。
如.吃盖饭抽象的说就是吃饭,吃饭具体的说就是吃什么。人类具体的说就是分女人和男人,人类抽象的说就是动物;
二.提出问题养狗社区
面向过程(C语言) | 面向对象(Java) |
流水线(步骤) | 模块化(分类) |
一件事"该怎么做" | 一件事"该让谁来做" |
狗饿了,狗吃了食物 | 属性:狗、食物、饿;动作:狗吃食物 |
强调的是“吃”,“狗”只是一个参数 | 强调的是“吃”,“狗”只是一个参数 |
如果使用C语言写会非常麻烦,因为它是按照顺序来的,但是每一只狗的作息是不一样的,使用C语言的话每一只狗都要写一遍非常麻烦;
如果使用Java写,我们只需要把这些狗的共性和特性提取出来,形成一个个模块(如.吃,睡觉,等等),让狗主人自己填写狗的作息;
使用我们使用Java写养狗社区;
package com.microsoft.bean;
// 狗类(狗属性)
public class Dogs {
// 狗的状态
// 下面每一个狗的状态,都是类中的一个成员,它们是类的重要组成部分;
// 成员变量:它们组成和构成了类,所有我们这么命名
// 狗名字
public String name;
// 狗种类
public String variety;
// 狗的年龄
public int age;
// 狗的食物
public String food;
// 狗的行为(就是狗的动作,在类中被称为行为)
public void eat() {
System.out.println(this.name+"狗吃饭");
}
public void sleep() {
System.out.println(this.name+"狗睡觉");
}
public void run() {
System.out.println(this.name+"狗正在奔跑");
}
}
一个项目只能有一个main方法,所以我们要定义一个测试文件为Application
import com.microsoft.bean.Dogs;
public class Application {
public static void main(String[] args) {
// 张大爷家的狗是狗类中的一个实例
// // 张大爷,注册APP
Dogs zhangDog = new Dogs();
// 张大爷设置狗的状态
zhangDog.name = "阿黄";
zhangDog.variety = "中华田园犬";
zhangDog.age = 2;
zhangDog.food = "剩菜剩饭";
// 张大爷设置狗现在的行为
zhangDog.eat();
}
}
三.方法与变量的分类
1.非静态变量与非静态方法
上面定义狗的一些状态与行为,没有使用Static,使用我们可以称为这些为非静态变量与非静态方法;
所以我们要调用时,要先实例化这个对象,所以new关键字
使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中的构造器的调用;(构造器我们后面会讲)
// 张大爷,注册APP,使用new实例化
// 格式:对象类型 对象名 = new 对象值;
Dogs zhangDog = new Dogs();
// 张大爷设置狗的状态
zhangDog.name = "阿黄";
zhangDog.variety = "中华田园犬";
zhangDog.age = 2;
zhangDog.food = "剩菜剩饭";
// 调用非静态变量:对象名.变量名
System.out.println("张大爷家狗的名字: " + zhangDog.name);
// 张大爷设置狗现在的行为
// 调用非静态方法:对象名.方法名
zhangDog.eat();
2.静态变量与静态方法
有Static关键字修饰的变量与方法,我们叫静态变量与静态方法;
// 狗所在的小区
public static String plot = "希望小区";
// 狗名字
public String name;
// 狗种类
public String variety;
// 狗的年龄
public int age;
// 狗的食物
public String food;
// 我们要给所以狗打疫苗
public static void injection(){
System.out.println("所以的狗,月底打疫苗");
}
// 张大爷,注册APP,使用new实例化
Dogs zhangDog = new Dogs();
// 张大爷设置狗的状态
zhangDog.name = "阿黄";
zhangDog.variety = "中华田园犬";
zhangDog.age = 2;
zhangDog.food = "剩菜剩饭";
// 调用静态变量使用:类名.变量名
// 原因静态变量是属于整个类的,不属于某个对象
System.out.println("张大爷的狗所在小区" +Dogs.plot);
// 调用静态方法属于:类名.方法名
// 原因静态方法是属于整个类的,不属于某个对象
Dogs.injection();
四.注销账号和null空指针异常
// 张大爷,注册APP
Dogs zhangDog = new Dogs();
// 张大爷家的狗是狗类中的一个实例
// 张大爷设置狗的状态
zhangDog.name = "阿黄";
zhangDog.variety = "中华田园犬";
zhangDog.age = 2;
zhangDog.food = "剩菜剩饭";
// 张大爷注销账号
zhangDog = null;
// 注销后就不能在调用否则会出现空指针异常
System.out.println("张大爷家狗的名字: " + zhangDog.name);
NullPointerException
原因:指针原本指向张大爷家的狗,注销账号后指向一个空白的区域
五.简单内存分析
第一步:加载Application类与静态方法(从这里可以看出静态变量与方法与类一起加载,所有对象都可以使用),进入main函数
第二步:加载Dogs类
第三步:张大爷注册app,使用Dogs zhangDog = new Dogs();,在栈生成引用变量名,对象生成在堆里,堆里的对象是通过Dogs类为模板生成,引用变量名指向它在堆中的地址;
第四步:赋值
六.OOP封装
问题:
pubilc 公有的,公共的-------用户可以随意修改(如.上面张大爷注册账号时可以随意填写狗的信息,如果在里面的东西与钱挂钩的话,那么用户也可以随意修改)
解决:
private 私有的------用户不能随意修改,我们给一个用户能设置,能获取,但不能随意设置,使用getset关键字,快捷方式Alt+insert
Ctrl+a全选,然后回车
this表示:本身调用者这个对象
package com.microsoft.bean;
public class Dogs {
// 狗所在的小区
public static String plot = "希望小区";
// 狗名字
private String name;
// 狗种类
private String variety;
// 狗的年龄
private int age;
// 狗的食物
private String food;
// 约束
public String getName() {
return this.name;
}
public void setName(String name) {
if (name.length() < 20) {
this.name = name;
}else {
System.out.println("你的狗名字过长");
}
}
public String getVariety() {
return variety;
}
public void setVariety(String variety) {
this.variety = variety;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0 && age <30){
this.age = age;
}else {
System.out.println("你的狗年龄错误");
}
}
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
// 我们要给所以狗打疫苗
public static void injection(){
System.out.println("所以的狗,月底打疫苗");
}
// 狗的行为(就是狗的动作,在类中被称为行为)
public void eat() {
System.out.println(this.name+"狗吃饭");
}
public void sleep() {
System.out.println(this.name+"狗睡觉");
}
public void run() {
System.out.println(this.name+"狗正在奔跑");
}
}
import com.microsoft.bean.Dogs;
public class Application {
public static void main(String[] args) {
// 张大爷,注册APP,使用new实例化
Dogs zhangDog = new Dogs();
// 张大爷设置狗的状态
// 输入使用set
zhangDog.setName("阿黄");
zhangDog.setVariety("中华田园犬");
zhangDog.setAge(10);
zhangDog.setFood("剩菜剩饭");
// 输出使用get
System.out.println(zhangDog.getAge());
}
}
出现问题,每一个成员变量都要写getset非常麻烦,所有出现了一个架包
下载完插件后,我们要下载架包
架包网站:Maven Repository: org.projectlombok » lombok (mvnrepository.com)
选择版本,点进去,然后jar下载
引入架包
然后将架包拖进去,接着选择作用范围
第一个表示全局,第二个表示这个项目,第三个表示模块
如果想使用结包还要启用注解
使用:特殊的可以单写,这个叫方法的重写,我们后面会讲
package com.microsoft.bean;
import lombok.Getter;
import lombok.Setter;
// 也可以写在一个成员变量后,只对一个成员变量起作用
@Getter
@Setter
public class Dogs {
// 狗所在的小区
public static String plot = "希望小区";
// 狗名字
private String name;
// 狗种类
private String variety;
// 狗的年龄
private int age;
// 狗的食物
private String food;
// 方法的重写
public void setName(String name) {
if (name.length() < 20) {
this.name = name;
}else {
System.out.println("你的狗名字过长");
}
}
public void setAge(int age) {
if (age > 0 && age <30){
this.age = age;
}else {
System.out.println("你的狗年龄错误");
}
}
// 我们要给所以狗打疫苗
public static void injection(){
System.out.println("所以的狗,月底打疫苗");
}
// 狗的行为(就是狗的动作,在类中被称为行为)
public void eat() {
System.out.println(this.name+"狗吃饭");
}
public void sleep() {
System.out.println(this.name+"狗睡觉");
}
public void run() {
System.out.println(this.name+"狗正在奔跑");
}
}
七.toString
// 张大爷设置狗的状态
zhangDog.setName("阿黄");
zhangDog.setVariety("中华田园犬");
zhangDog.setAge(10);
zhangDog.setFood("剩菜剩饭");
// 如果我们想要输出张大爷家的狗所有信息需要写四条输出语句
// 如果使用toString,我们只需写一条输出语句
快捷方式Alt+insert,然后全选,生成
@Override
public String toString() {
return "Dogs{" +
"name='" + name + '\'' +
", variety='" + variety + '\'' +
", age=" + age +
", food='" + food + '\'' +
'}';
}
也可以直接使用架包引入
import lombok.ToString;
// 也可以写在一个成员变量后,只对一个成员变量起作用
@ToString
效果
补充: 补充如果要使用图中三个方法,可以引入架包@Date
八.构造方法
问题:
张大爷想要在注册账号时,填写狗的基本信息
解决:
使用构造函数,初始化对象(实例);
/*
类中的构造器也称为构造方法,是在进行创建对象(new)的时候必须调用的;
构造器有两大特点:
1.必须和类的名字相同
2.必须没有返回值类型,也不能写void
*/
// 无参数构造函数(无参构造器),每创建一个类,都会有一个无参构造器;
// 如果是系统自带的类会默认创建,要是自己引入的类需要自己,手动创建;
public Dogs() {
}
// 有参数的构造函数(有参构造),一但定义有有参构造,无参构造就必须定义;
// 有参构造使用了方法的重载
public Dogs(String name, String variety, int age, String food) {
this.name = name;
this.variety = variety;
this.age = age;
this.food = food;
}
import com.microsoft.bean.Dogs;
public class Application {
public static void main(String[] args) {
// 张大爷,注册APP,并设置狗的基本信息
Dogs zhangDog = new Dogs("阿黄","中华田园犬",10,"剩菜剩饭");
System.out.println("张大爷家的狗所有信息" +zhangDog);
}
}
总结:在创建对象时是有调用构造器来初始化值,无参构造默认存在,有参构造是方法重载;
快捷方式Alt+insert,然后选择初始化对象
九.垃圾回收机制
ava自动会进行垃圾回收,所有我们不用管
如果需要手动,使用:
System.gc();
十.关键字Static
问题:
静态变量与方法加private,会出现输出不了的问题;
解决:
public static String getPlotInstance(){
return plot;
}
静态不用写set
System.out.println("张大爷家狗住的小区:" +Dogs.getPlotInstance());
1.Static单例设计模式
单例设计模式是一种创建对象的设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例;
简单来说就是:不提供new的方法,只提供对外操作的方法;
package com.microsoft.bean;
public class Earth {
// new 一个新的地球,自己new自己,只有Earth类内可以修改
private static Earth earthInstance = new Earth();
// 外部无法new新的Earth
private Earth() {
}
// 提供外部操作方法
public static Earth getEarthInstance(){
return earthInstance;
}
public void showMessage(){
System.out.println("Hello Earth!");
}
}
// 获取唯一可用的对象
Earth object = Earth.getEarthInstance();
// 显示消息
object.showMessage();
2.静态代码块
package com.microsoft.bean;
public class Earth {
{
System.out.println("匿名代码块");
}
static {
System.out.println("静态代码块");
}
public Earth() {
System.out.println("构造方法");
}
public static void main(String[] args) {
System.out.println("第一次调用");
Earth temp = new Earth();
System.out.println("\n第二次调用");
Earth tempTwo = new Earth();
}
}
原因:Static关键字是与类一起加载所有首先调用,接着是类中的匿名代码块,然后构造方法,
还有值得注意的是静态代码块只调用一次;
3.静态导入包
导入前调用方法:类名.方法
System.out.println(Math.random());
导入后调用方法:方法
import static java.lang.Math.random;
System.out.println(random());
十一.内部类
1.成员内部类
package com.microsoft.bean;
public class Earth {
// 外部类
public class Sun{
// 内部类
public void fuck() {
System.out.println("这是内部类");
}
}
}
// 创建内部类对象:可以在外部类中创建内部类的对象
Earth earth = new Earth();
Earth.Sun sun = earth.new Sun();
// 调用
sun.fuck();
2.静态内部类
package com.microsoft.bean;
public class Earth {
public static class Sun{
public void fuck() {
System.out.println("这是静态内部类");
}
}
}
// 创建内部类对象:可以直接通过类名创建静态内部类的对象
Earth.Sun temp = new Earth.Sun();
temp.fuck();
3.局部内部类
package com.microsoft.bean;
public class Earth {
public static void main(String[] args) {
class drop{
public void man() {
}
}
}
}
4.匿名内部类
这个要学完接口后,再回来看