自学Java基础知识第六天

day06

1. 面向对象思想

  1. 面向对象 : 就是一种编程思想, 编程思维
  2. 面向过程与面向对象比较:

   a : 面向过程 : 有一个需求要实现, 我需要如何实现, 强调需求实现过程, 实现步骤

   b : 面向对象 : 有一个需求要实现, 让谁去实现

 

  举例 : 打扫卫生需求实现

  a : 面向过程思维 : 想象自己如何能够将打扫卫生过程实现, 摆桌子, 摆凳子, 扫地, 拖地, 关空调, 关门

  b : 面向对象思维 : 让小红打扫卫生

 

面向过程是面向对象的基础, 面向对象基于面向过程

 

  1. 面向对象优势:

1) 更符合人类的思考习惯

2) 简化代码的设计难度

3) 由实施者变成指挥者

 

  1. 面向对象特征:

1) 封装

2) 继承

3) 多态

 

 

2. 类与对象

2.1 类与对象的比较

  1. : 对于事物的抽象描述, 抽象表现形式

   举例 : 玩具模型, 有两只眼睛, 一张嘴巴, 能说话

  1. 对象 : 对于事物具体表现形式

   举例 : 葫芦娃, 就是对于玩具模型事物的具体表现形式

 

 

2.2 类的组成

  1. 类的组成 : 类是属性和行为的集合

  a : 属性, 表示对于事物的特征描述, 将事物具有的属性以变量形式定义, 只不过需要将这个变量定义在类中方法外的位置上, 称为成员变量或者全局变量

  b : 行为, 就是方法功能的定义

     修饰符  返回值类型 方法名(参数列表){

}

  注意 : 前面的代码,方法的修饰符写成public static, 现在方法修饰符可以直接使用public, 暂且不需要写static

 

举例 : 人类Person

属性 : 姓名, 年龄

行为 : 吃饭, 睡觉...

 

代码

package com.ujiuye.object;

public class Person {

// 1. 定义出成员变量, 表示Person人类的属性(特征)

// 数据类型  变量名 = 变量值;

// 1) 姓名

String name = "张三";

// 2) 年龄, 通常类中的成员变量一般不给值

// 类型中的成员变量, 定义的时候可以不赋值, JVM虚拟机会给每一个成员变量

// 进行一个默认的赋初值动作

int age; // 默认值为0

 

// 2. 定义出Person人类具有方法功能

public void eat() {

System.out.println(name+"一天吃三顿饭");

}

 

    public void sleep() {

     System.out.println(name + "一共睡觉" + age + "");

    }

}

 

 

2.3 对象的创建和使用

  1. 创建对象语法结构:

   数据类型  变量名 = new 数据类型();

类名     对象名 = new 类名();

 

  1. 说明: 类名     对象名 = new 类名();

1) 类名 : 表示对象是属于什么数据类型, 自定义类, JDK提供的核心类库,都是引用数据类型

2) 对象名 : 变量名, 符合标识符组成规范, 小驼峰原则, 第一个英文单词全小写, 从第二个英文单词开始首字母大写  getSum

3) = : 赋值运算符, 将对象在内存中占有的空间地址赋值给等号左边的变量名

4) new : 关键字, 表示新建概念, 为对象在内存中开辟空间存储对象中的数据

5) 类名 : 与前面的类名保持一致

6) () : 表示构造方法调用(铺垫)

 

举例 : Person p = new Person();

 

  1. 使用对象:

   对象名.属性 = ;  // 给对象中的成员变量赋值

   变量 = 对象名.属性; // 获取对象中的成员变量值

   对象名.方法名(实际参数); // 调用对象中的方法功能

 

代码

package com.ujiuye.object;

public class TestPerson {

public static void main(String[] args) {

// 1. 创建出一个Person类型对象

// 类名     对象名 = new 类名();

Person p = new Person();

// 2. 使用对象中成员变量

System.out.println(p.name);// 张三

System.out.println(p.age);// 0

 

 

Person p1 = new Person();

p1.name = "小红";

p1.age = 20;

System.out.println(p1.name);

System.out.println(p1.age);

 

// 3. 对象中的方法调用

p1.eat();

p1.sleep();

}

}

 

 

案例 : 定义一个小汽车类Car, 小汽车具有属性 : 轮胎个数(num), 和颜色(color), 小汽车具有run功能, 要求run方法运行时, 能将小汽车的属性描述出来

 

代码

package com.ujiuye.object;

public class Car {

// 轮胎个数(num)

int num;

// 颜色(color)

String color;

 

public void run() {

 System.out.println(color+"颜色的小汽车,"

     + num + "个轮子,正在马路上跑");

}

}

 

package com.ujiuye.object;

public class TestCar {

public static void main(String[] args) {

// 1. 创建出一个Car对象

Car c = new Car();

System.out.println(c);

c.num = 4;

c.color = "";

c.run();

 

Car c1 = new Car();

c1.num = 8;

c1.color = "绿";

c1.run();

}

}

 

 

2.4 创建对象在内存中的理解

  JVM虚拟机将其在内存中所占有空间区域进行划分, 分成了5块空间, 每块不同的空间对于java代码有不同的执行作用

  1. 栈内存 : 方法调用进栈内存中运行, 方法运行完毕, 弹出栈内存, 释放空间
  2. 堆内存 : 引用数据类型创建对象在堆内存中开辟空间, 当对象再无可用之处, 堆内存空间需要释放掉
  3. 方法区(数据共享) : 类型的.class字节码文件存储在方法区中, 方法区中存储静态成员, 常量池也存储在方法区中

 

2.4.1 两个对象在内存中的存储

 

 

 

 

 

 

  1. 先将Car.class字节码文件加载进方法区中, 进入内存一次即可让Car类型任意使用
  2. main方法需要运行, 于是进入到栈内存中运行
  3. main方法中第一句代码 : Car c = new Car();

   a : 通过new关键字在堆内存中开辟空间, 存储Car对象中的成员变量

   b : JVM虚拟机,Car对象中的所有非静态成员变量加载进堆内存中, 为每一个成员进行默认的赋初值动作

   int--->0

   double--->0.0

   char--->’ ’

   boolean---> false

   引用数据类型--->null

  c : 将对象在堆内存中空间赋值, 赋值到栈内存中的对象引用处

  1. 使用对象名.调用方法, 方法进栈内存运行, 方法会记录调用的对象地址, 为了找到对应的变量使用的出处
  2. 引用数据类型,每次通过new关键字创建对象, 每次都是在堆内存中创建新的地址空间

 

 

2.4.2 两个引用指向同一块内存

代码

package com.ujiuye.object;

public class Car {

// 轮胎个数(num)

int num;

// 颜色(color)

String color;

 

public void run() {

 System.out.println(color+"颜色的小汽车,"

     + num + "个轮子,正在马路上跑");

}

}

 

package com.ujiuye.object;

public class TestCar {

public static void main(String[] args) {

// 1. 创建出一个Car对象

Car c = new Car();

System.out.println(c);

c.num = 4;

c.color = "";

c.run();

 

Car c1 = new Car();

System.out.println(c1+"----");

c1.num = 8;

c1.color = "绿";

c1.run();

 

// c1是一个对象引用, c2也是一个对象引用, 现在c1c2两个引用指向同一块内存空间

Car c2 = c1;// 表示赋值, c1的地址值赋值给c2, 证明c1c2指向同一块内存空间

System.out.println(c2 + "-----");

System.out.println(c2.color);// 绿

}

}

 

2.5 匿名对象

  1. 匿名对象 : 没有名字的对象

  a : 有名对象  Person  p = new Person(); // p表示Person类型对象(对象名)

  b : 匿名对象  new Person();  匿名对象一样在堆内存中开辟空间, JVM虚拟机一样将对象非静态成员变量加载进内存, 默认赋初值

 

  1. 匿名对象如何使用:

  a : 匿名对象只能使用一次, new Person().调用属性或者调用方法功能;

  b : 虽然匿名对象只能使用一次, 但是如果一个对象无法再使用, 那么这个对象在堆内存中占有的空间很快就会变成垃圾, 等待JVM虚拟机垃圾回收机制将空间清理掉,于是匿名对象在内存中占有时间很短, 因此变相优化内存的使用

  c : 如果某一个类型中的属性或者方法, 只调用一次, 那么可以使用匿名对象实现

  

注意 : 通常不会使用匿名对象给成员变量进行赋值, 因为赋值之后其值无法保存, 因此赋值就没有意义

 

代码

package com.ujiuye.object;

public class Demo01_匿名对象 {

public static void main(String[] args) {

//引用数据类型,每次通过new关键字创建对象, 每次都是在堆内存中创建新的地址空间

         // 1. 定义出一个匿名对象

 new Car().run();

 

 System.out.println(new Car().color);

 

 // 2. 通常不会使用匿名对象给成员变量进行赋值

 new Car().num = 8;

 System.out.println(new Car().num);

 

 Car c1 = new Car();

 Car c2 = new Car();

}

}

 

 

2.6 基本数据类型和引用数据类型作为方法参数

  1. 基本数据类型作为方法参数案例1

 

 

 

 2.基本数据类型作为方法参数案例2

 

 

3.引用:

 

 

 

 

 

 

 

2.7 成员变量和局部变量的比较

 

  1. 定义位置不同:

  a : 成员变量, 定义在类中,方法外

  b : 局部变量, 定义在方法内部的变量,或者是定义在方法的参数列表上的变量

  1. 内存中存储的位置不同:

  a : 成员变量, 跟着对象存储在堆内存中

  b : 局部变量, 跟着方法存储在栈内存中

  1. 生命周期不同:

  a : 成员变量, 对象创建时成员变量跟着进入内存出现, 当对象再无使用地方, 对象内存空间变成垃圾,成员变量生命也随之结束

  b : 局部变量, 方法调用局部变量进入内存,当方法运行完毕, 方法弹栈死亡, 局部变量跟着方法消亡

  1. JVM虚拟机初始化值不同

  a : 成员变量, 当创建对象时, JVM虚拟机自动给所有非静态成员变量进行默认的赋初值

  b : 局部变量, JVM不会默认赋初值, 于是定义在方法中的变量, 不赋值不能使用

 

 

3. 封装

3.1 封装的概述

  1. 封装面向对象中的一大特征
  2. 封装 : 隐藏事物属性或者实现细节, 对外提供公共访问方式
  3. 封装在java代码中的体现形式, 非常多种, 举例 : 方法本身就是一种封装概念,类本身也是一种封装概念...
  4. 封装优势:

1) 因为隐藏事物的实现细节, 提高代码的安全性

2) 提高代码的复用性

 

3.2 private关键字

  1. private : 关键字, 表示私有的, 私密的
  2. private关键字修饰:

1) 修饰成员变量(最常见使用方式, 今天掌握第一种使用)

2) 修饰方法

3) 构造方法

4) 内部类

 

  1. 使用private修饰后的效果 : 只能在当前类型中使用, 出了当前类之外的所有类型,不能直接使用private修饰的成员

 

  1. private关键字的使用只是封装的其中一种表现方式

 

案例 : 定义Student学生类, 属性 : 姓名, 年龄, 学号, 功能 : 学习study

 

代码

package com.ujiuye.privatedemo;

public class Student {

// 属性 : 姓名, 年龄, 学号

String name;

// age只能在Student类中使用

private int age;

String id;

 

// 定义出学习功能

public void study() {

System.out.println(name + "学生在学习");

}

}

 

package com.ujiuye.privatedemo;

public class TestStudent {

public static void main(String[] args) {

        // 1. 定义出一个学生对象

Student s = new Student();

 

// 问题 : -20的年龄不安全的数据,于是在Student中私有修饰

// 因为age使用private修饰, 外类中不能直接操作使用

// s.age = -20;

// System.out.println(s.age);

s.age = 25;

s.name = "张三";

s.id = "001";

s.study();

}

}

 

 

3.3 SetterGetter方法

  1. 给私有成员变量提供对外的公共的访问方式
  2. Setter方法 : 给私有成员变量赋值的方法功能, 外界无法直接访问私有成员, 只能通过set方法对私有变量进行赋值, 因此set方法中, 逻辑如何要求进行赋值,只能如何赋值, 提高代码的安全性
  3. Getter 方法 : 获取私有成员变量的值
  4. 实际开发中, 实体类(真真正正存在的事物)中的属性(成员变量),通常都会使用private进行私有修饰, 为了不让外界直接给成员进行赋值, 从而提高代码的安全性

 

代码

package com.ujiuye.privatedemo;

public class Student {

// 属性 : 姓名, 年龄, 学号

String name;

// age只能在Student类中使用

private int age;

String id;

 

// 为私有成员变量age提供对外的公共的访问方式

// 1) Setter方法 : 给成员变量age赋值

public void setAge(int a) {

if(a > 0 && a <= 150) {

age = a;

}else {

System.out.println("输入的年龄有误,使用默认年龄0");

}

}

 

// 2) Getter 方法 : 获取成员变量age的值

public int getAge() {

return age;

}

 

// 定义出学习功能

public void study() {

System.out.println(name + "学生在学习");

}

}

 

package com.ujiuye.privatedemo;

public class TestStudent {

public static void main(String[] args) {

        // 1. 定义出一个学生对象

Student s = new Student();

 

// 问题 : -20的年龄不安全的数据

// 因为age使用private修饰, 外类中不能直接操作使用

// s.age = -20;

// System.out.println(s.age);

// s.age = 25;

 

/*s.setAge(-90);

System.out.println(s.getAge());*/

 

s.setAge(27);

System.out.println(s.getAge());

s.name = "张三";

s.id = "001";

s.study();

}

}

 

 

3.4 变量访问原则和this关键字

  1. 变量访问就近原则 :

   使用一个变量时, 优先寻找最近的一次变量定义使用, 如果局部变量有定义,优先使用局部变量, 如果没有局部变量定义, 使用成员变量

  1. this关键字 : 表示当前类型对象的使用, this关键字表示一个对象

   功能1 : 主要可以进行成员变量和局部变量重名问题的区分

           带有this关键字的变量表示成员变量的使用

 

  1. 一个类,可以创建出无数对象, 每次new都是一个新对象, this关键字到底可以表示哪一个对象

   哪个对象调用了带有this的方法, 那么this关键字就代码哪个对象

 

代码

package com.ujiuye.privatedemo;

public class Demo01_变量访问原则 {

    // 成员变量

int i = 10;

 

public void useI() {

// 局部变量

int i = 99;

// 2. i值的使用利用了变量的就近访问原则

System.out.println(i);// 99

// 3. 调用重名的成员变量i

System.out.println(this.i);// 10

System.out.println(this + "this-------------");

}

 

public static void main(String[] args) {

// 1. 创建出一个当前类型对象

Demo01_变量访问原则 demo = new Demo01_变量访问原则();

System.out.println(demo.i);// 10

// 哪个对象调用了带有this的方法, 那么this关键字就代码哪个对象

demo.useI();// 99

System.out.println(demo+"----");

 

Demo01_变量访问原则 demo1 = new Demo01_变量访问原则();

System.out.println(demo1);

demo1.useI();

}

}

 

 

3.5 构造方法

  1. 构造方法 : 构造器, 构造函数, 使用英文单词Constructor 表示
  2. Person p = new Person();

   对象创建的过程中, ()表示构造方法的调用

   构造方法主要功能就是为了给对象的成员变量进行赋值, 当创建对象时, JVM虚拟机主动调用构造方法, 当构造执行完, 对象也创建完毕, 对象中成员变量有值

 

  1. 构造方法的语法结构:

   修饰符  构造方法名(参数列表){

        // 给成员变量进行赋值;

}

  1. 说明:

1) 修饰符 : 通常使用public公共修饰

2) 构造方法没有返回值类型, void都不写

3) 构造方法名 : 必须和类名一致

4) 因为构造方法没有返回值类型, 所以不需要写return ,如果一定要写return;

 

  1. 构造方法运行机制:

1) 每次创建对象, JVM虚拟机主动调用指定构造方法一次

2) 构造方法无法通过对象名.主动调用

 

代码

package com.ujiuye.constructor;

public class ConstructorClass {

    private String name;

    private int age;

    

    // 定义出构造方法

/*    修饰符  构造方法名(参数列表){

        // 给成员变量进行赋值;

}*/

 

    public ConstructorClass(String name, int age) {

     this.name = name;

     this.age = age;

    }

    

   /* public ConstructorClass() {

     System.out.println("我是构造,执行了");

    }*/

     

    // alt + shift + s : 快捷键, 可以到里面选择需要生成的代码, 包括setget

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;

}   

}

 

package com.ujiuye.constructor;

public class TestCon {

public static void main(String[] args) {

// ConstructorClass(): 表示调用ConstructorClass()空参数构造

// ConstructorClass cc = new ConstructorClass();

 

// 构造方法调用需要传递实际参数

ConstructorClass cc1 = new ConstructorClass("张三",20);

System.out.println(cc1.getName());

System.out.println(cc1.getAge());

 

// 构造方法不能主动调用, 只能依靠每次创建对象JVM虚拟机主动调一次

// cc1.ConstructorClass("张三",20);

}

}

 

posted @ 2020-09-07 19:27  master_hxh  阅读(112)  评论(0编辑  收藏  举报