Java基础专栏
Java基础(第七期)
面相对象
面向对象(Object-oriented)是一种编程思想和方法,它将程序的设计和组织建立在对象的概念上。在Java中,每个对象都是类的一个实例,而类定义了相同类型对象所共有的属性和行为。
面向对象编程的主要目标是通过封装、继承和多态来提高代码的可重用性、可维护性和可扩展性。下面是面向对象的一些重要特征和用途:
- 封装(Encapsulation):将数据和相关操作封装在一个对象中,隐藏内部实现细节,只暴露必要的接口,提供更好的代码隔离和模块化。
- 继承(Inheritance):通过继承关系,子类可以继承父类的属性和方法,并且可以添加自己独特的功能,减少代码冗余,提高代码复用性。
- 多态(Polymorphism):允许使用统一的接口处理不同类型的对象,提高代码灵活性和可扩展性,简化代码逻辑。
- 类和对象:通过类定义对象的属性和行为,并通过实例化创建对象,进行数据操作和方法调用。
- 抽象类和接口:抽象类定义了一组相关的对象的通用特性,接口定义了一组对象必须实现的方法。它们提供了代码规范和约束,增加了代码的可读性和可维护性。
面向对象编程使得代码更易于理解和维护,提供了更高的代码复用性和可扩展性。它能够将复杂的问题分解为一系列相互关联的对象,使程序更加模块化和结构化,有助于团队合作和大规模软件开发。
- 本期先学习如何自己设计面向对象
一、类和对象
1.1 类是什么
作用:Java中想要创建对象,必须先要有类的存在。
类是一组相关属性和行为的集合,可以理解为类就是一张对象的设计图
。
- 类可以创建出多个对象。
1.2 类的组成
类的组成:
1. 成员变量:
定义在类中,且在成员方法外的变量就是成员变量,定义方法个普通的定义的方法一样。
*2.* 成员方法:
*定义在累中,定义的方法和普通的函数方法是一样的,只不过需要取出* *static* *关键字。*
代码示例:
// 定一成员变量
String name = "刘不住";
int age = 24;
// 定义成员方法
public void functionFn() {
System.out.println("成员方法");
}
测试类中使用类(带有main方法的就是测试类):
- 创建对象的格式:
类名 对象名 = new 类名();
- 使用类中的成员变量格式:
对象名.成员变量
- 使用类中的成员方法格式:
对象名.方法名
public static void main(String[] args) {
// 使用类 创建实例对象
Student stu1 = new Student();
// 使用成员变量
System.out.println("姓名为:" + stu1.name);
System.out.println("年龄为:" + stu1.age);
// 使用成员方法
stu1.functionFn();
}
/*
输出结果:
姓名为:刘不住
年龄为:24
成员方法
*/
1.3 类使用的细节
1) 打印类名的时候,可以看到类名地址:
com.liujintao.oop.Student@380fb434
@: 依旧是分隔符
con.liujintao.opp: 包名(全类名)
@后面的:就是地址了。
2) 成员变量不要初始化:
因为我们的类就是一张设计图,不能把一些东西写死吧!所以我们不要给初始值。让它使用类型的默认值。
谁要使用我的图纸(类),谁就自己写内容,意思就是框架我帮你搭建好!其他的我就不管,自定义就好了。
// 使用类 创建实例对象
Student stu1 = new Student();
// 自定义成员变量值
stu1.name = "刘不住";
stu1.age = 24;
// 使用成员变量
System.out.println("姓名为:" + stu1.name);
System.out.println("年龄为:" + stu1.age);
1.4 类的定义和练习1
定义一个手机类(Phone):
属性:品牌、颜色、价格。
行为:打电话、发短信
编写一个手机测试类:
创建一个手机对象,并自定义初始值
然后使用里面的成员变量和成员方法。
- 定义一个手机类
package com.liujintao.test;
/**
* 这是一个手机类
*/
public class Phone {
// 定义成员变量(注意初始值让调用者自己自定义)
String brand;
String color;
int price;
// 定义成员方法
public void call (String name) {
System.out.println("给余大嘴(余总)打电话");
}
public void sendMessage () {
System.out.println("群发消息:遥遥领先!");
}
}
- 定义一个测试手机类
package com.liujintao.test;
public class PhoneTest {
public static void main(String[] args) {
// 1、通过类创建实例对象
Phone ph = new Phone();
// 2、 自定义成员变量值
ph.brand = "HUAWEI Mate60Pro";
ph.color = "雅川青";
ph.price = 6999;
// 查看成员变量
System.out.println("品牌为:" + ph.brand);
System.out.println("颜色:" + ph.color);
System.out.println("价格:" + ph.price);
// 3、使用成员方法
String name = "余大嘴(余总)";
ph.call(name);
ph.sendMessage();
}
}
- 输出结果:
品牌为:HUAWEI Mate60Pro
颜色:雅川青
价格:6999
给余大嘴(余总)打电话
群发消息:遥遥领先!
1.5 类的定义和练习2
1、编写一个图书类:
属性:编号、书名、价格
行为:展示(图书所有的属性)
2、编写一个图书测试类:
创建三个图书对象,分别赋值为:
(001, 三国, 88.88)
(002, 水浒,88.88)
(003,富婆通讯录, 10000)
调用三个对象,各自的show方法展示属性信息
-
定义一个图书类:
package com.liujintao.test; public class Book { // 1. 定义成员方法 String id; String name; double price; // 2.定义成员方法 public void show() { System.out.println("id:" + id); System.out.println("书名:" + name); System.out.println("价格:" + price); } }
-
定义一个图书测试类:
package com.liujintao.test;
public class BookTest {
public static void main(String[] args) {
// 1. 创建实例对象
Book bk1 = new Book();
Book bk2 = new Book();
Book bk3 = new Book();
// 2. 给成员变量赋值
bk1.id = "001";
bk1.name = "三国";
bk1.price = 88.88;
bk2.id = "002";
bk2.name = "水浒";
bk2.price = 88.88;
bk3.id = "003";
bk3.name = "富婆通讯录";
bk3.price = 10000;
// 3. 使用成员方法,查看信息
bk1.show();
bk2.show();
bk3.show();
}
}
- 执行结果:
id:001
书名:三国
价格:88.88
id:002
书名:水浒
价格:88.88
id:003
书名:富婆通讯录
价格:10000.0
二、对象内存图
单个对象的内存图:
两个对象的内存图:(方法共用内存图)
两个引用指向相同内存图:
能看的懂这是三个内存图,并且能够简述执行流程。说明对于数据类型的存储和对象和方法的执行机制掌握的非常扎实了。
三、成员变量和局部变量
3.1 之间的区别
区别 | 成员变量 | 局部变量 |
---|---|---|
类中位置不同 | 方法外 | 方法中 |
初始化值不同 | 有默认初始值 | 没有,使用前需要初始化 |
内存位置不同 | 堆内存 | 栈内存 |
声明周期不同 | 随着对象的创建而存在,随着对象的消失而消失 | 随着方法的调用而存在,随着方法的结束而消失 |
作用域 | 在子级的做归属花括号内(类的{}) | 归属于自己的花括号内(方法函数{}) |
四、this 关键字
当局部变量和全局变量重名的时候,JAVA使用就近原则访问作用域。
当我们需要访问远的那个,此时就得使用 this。
4.1 this作用
Student类:
package com.liujintao.mythis;
public class Student {
String name;
public void sayHello (String name) {
System.out.println(name);
System.out.println(this.name);
}
}
ThisDemo测试类:
package com.liujintao.mythis;
public class ThisDemo {
public static void main(String[] args) {
Student stu = new Student();
stu.name = "钢门吹雪";
stu.sayHello("西域狂鸭");
}
}
-
输出结果:就近原则:访问局部的变量:
西域狂鸭
钢门吹雪
-
this 可以调用本类的成员。
4.2 this省略规则
在访问本类成员方法的时候,可以省略 this 关键字。
在访问本类成员变量的时候,没有同名的变量的前提下,可以省略 this 关键字。
4.3 this到底是什么
this:代表当前类对象(实例对象)的引用(地址),谁调用就指向谁。
4.4 this 内存图
this总结
this可以调用本类成员
this代表:当前类对象的引用(地址)。
例如:stu.age == this.age
五、构造方法(构造器)
构造方法:
- 初始化一个新的对象
- 构建,
创造对象的时候,所调用的方法
格式:
- 方法名与类名相同,大小写也要一致
- 没有返回值类型,连void都没有
- 没有具体的返回值(不能由retur带回结果数据)
5.1 简单的代码演示:
Student类
package com.liujintao.constructor;
public class Student {
public Student () {
System.out.println("我是Student类的构造方法");
}
}
StudentTest测试类:
package com.liujintao.constructor;
/*
构造方法(构造器)
*/
public class StudentTest {
public static void main(String[] args) {
Student stu = new Student();
}
}
运行结果为:
我是Student类的构造方法
- 类被new的时候就会调用构造方法。
Student stu1 = new Student();
Student stu2 = new Student();
Student stu3 = new Student();
我是Student类的构造方法
我是Student类的构造方法
我是Student类的构造方法
new几次我就调用几次
5.2 构造方法的作用
- 本质作用:创建对象
- 结合运行来看:可以在创建对象的时候,给对象中的数据初始化。
如下:
Student:
package com.liujintao.constructor;
public class Student {
String name;
int age;
public Student () {
name = "张三";
age = 18;
}
}
StudentTest:
package com.liujintao.constructor;
/*
构造方法(构造器)
*/
public class StudentTest {
public static void main(String[] args) {
Student stu1 = new Student();
System.out.println("姓名为:" + stu1.name);
System.out.println("年龄为:" + stu1.age);
}
}
运行结果:
姓名为:张三
年龄为:24
- 但是数据又写死了,得用传参解决问题!!!
解决方法:如下参考
public Student (String name, int age) {
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
Student stu1 = new Student("张三", 24);
System.out.println("姓名为:" + stu1.name);
System.out.println("年龄为:" + stu1.age);
Student stu2 = new Student("李四", 28);
System.out.println("姓名为:" + stu2.name);
System.out.println("年龄为:" + stu2.age);
}
- 这样参数随便自定义,只要符合要求。new一次我就执行一次
运行结果:
姓名为:张三
年龄为:24
姓名为:李四
年龄为:28
5.3 构造方法的注意事项
每创建一次就会执行一次
- 一个类中,没有编写构造方法,系统会默认提供一个
默认、无参
的构造方法 - 一个类中,如果手动编写构造方法,系统将不会在提供那个默认的无参构造
- 构造方法不允许手动调用
- 同时他也存在方法重载
- 建议,无参和有参构造都自己手动添加上
5.4 构造方法执行流程图
new 开辟堆空间
Student()调用构造方法
然后创建实例对象
六、封装
将需要处理的数据封装到对象里面去。
- 更好的维护数据
- 使用者无需关心内部实现,只要知道如何使用就行了
6.1 封装的设计规范
合理隐藏,合理暴露
犹如一辆汽车,开车的人只需要知道一些常用的操作就可以了,不需要知道它内部是如何运作设计的。
6.2 权限修饰符
- 修饰成员变量和成员方法
private:只能在本类中操作
default:同一个类,同一个包下(默认的)
protected:同一个类,同一个包中,不同包的子类。
public: 可以再任意位置访问
6.3 private私有化成员变量的使用练习
Student
package com.liujintao.encapsulation;
public class Student {
// 使用权限修饰符私有化成员变量
private int age;
public void setAge(int age) {
if (age >= 1 && age < 120) {
this.age = age;
System.out.println("您的年龄为:" + age);
} else {
System.out.println("年龄输入有误!");
}
}
public int getAge() {
return age;
}
}
StudentTest测试类:
package com.liujintao.encapsulation;
public class StudentTest {
public static void main(String[] args) {
Student stu = new Student();
stu.setAge(18);
stu.getAge();
}
}
输出结果:
您的年龄为: 18
七、javaBean
javaBean : 实体类:封装数据的类
1、这个类中的成员变量都要私有化,并且要对外提供getxxx 和 setxxx方法。
2、类中要提供无参、带参构造方法。
3、只负责数据存储。
- javaBean用于存取数据的,业务处理分离到别的类处理。便于维护。
package com.liujintao.domain;
public class Student {
// 1. 成员变量私有化
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
}
八、面向对象综合练习:电影信息系统
需求:
- 展示系统中的全部电影(每部电影展示、名称、平分)。
- 允许用户根据电影编号(id)查询出某个电影的详细信息。
1. 将JavaBean数据类封装好
package com.liujintao.domain;
/**
* JavaBean
*/
public class Movie {
private int id;
private String title;
private String time;
private double score;
private String area;
private String type;
private String director;
private String starring;
public Movie() {
}
public Movie(int id, String title, String time, double score, String area, String type, String director, String statting) {
this.id = id;
this.title = title;
this.time = time;
this.score = score;
this.area = area;
this.type = type;
this.director = director;
this.starring = statting;
}
/**
* 获取
* @return id
*/
public int getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setIdl(int id) {
this.id = id;
}
/**
* 获取
* @return title
*/
public String getTitle() {
return title;
}
/**
* 设置
* @param title
*/
public void setTitle(String title) {
this.title = title;
}
/**
* 获取
* @return time
*/
public String getTime() {
return time;
}
/**
* 设置
* @param time
*/
public void setTime(String time) {
this.time = time;
}
/**
* 获取
* @return score
*/
public double getScore() {
return score;
}
/**
* 设置
* @param score
*/
public void setScore(double score) {
this.score = score;
}
/**
* 获取
* @return area
*/
public String getArea() {
return area;
}
/**
* 设置
* @param area
*/
public void setArea(String area) {
this.area = area;
}
/**
* 获取
* @return type
*/
public String getType() {
return type;
}
/**
* 设置
* @param type
*/
public void setType(String type) {
this.type = type;
}
/**
* 获取
* @return director
*/
public String getDirector() {
return director;
}
/**
* 设置
* @param director
*/
public void setDirector(String director) {
this.director = director;
}
/**
* 获取
* @return statting
*/
public String getStarring() {
return starring;
}
/**
* 设置
* @param starring
*/
public void setStarring(String starring) {
this.starring = starring;
}
}
2.业务逻辑类
package com.liujintao.test;
import com.liujintao.domain.Movie;
import java.util.Scanner;
public class MovieService {
// 提升为成员变量,并合理隐藏
private Movie[] movies;
private Scanner sc;
/**
* 带参构造器:获取JavaBean中数据
*
*/
public MovieService(Movie[] movies) {
this.movies = movies;
}
/**
* 启动电影信息管理系统
*/
public void start() {
this.sc = new Scanner(System.in);
lo:
while(true) {
System.out.println("----------电影信息系统----------");
System.out.println("请输入您的选择");
System.out.println("1.查询全部电影信息");
System.out.println("2.根据id查询电影信息");
System.out.println("3.退出");
int choice = sc.nextInt();
switch(choice) {
case 1:
queryMoviesInfo();
break;
case 2:
queryMoviesById();
break;
case 3:
System.out.println("退出");
break lo;
default:
System.out.println("您的输入有误!");
break;
}
}
}
/**
* 通过编号:展示电影所有信息
*/
private void queryMoviesById() {
System.out.println("请输入电影的id号:");
int id = sc.nextInt();
for (int i = 0; i < movies.length; i++) {
if (movies[i].getId() == id) {
System.out.println("编号:" + movies[i].getId() + "-电影名:-" + movies[i].getTitle() + "-上映时间:-" + movies[i].getTime() + "-评分:-" + movies[i].getScore() + "-地区-" + movies[i].getArea() + "-电影类型-" + movies[i].getType() + "-导演-" + movies[i].getDirector() + "-主演-" + movies[i].getStarring());
return;
}
}
// 没找到!
System.out.println("您输入的编号不存在!");
}
/**
* 展示电影系统中全部的电影(名称、评分)
*/
private void queryMoviesInfo() {
for (int i = 0; i < movies.length; i++) {
Movie movie = movies[i];
System.out.println("电影名:" + movie.getTitle() + "---评分:" + movie.getScore());
}
}
}
3.测试类(main函数类)
package com.liujintao.test;
import com.liujintao.domain.Movie;
public class MovieTest {
public static void main(String[] args) {
// 构造器初始数据
Movie movie1 = new Movie(1, "东八区的先生们", "2022", 2.1, "中国大陆", "剧情 喜剧", "夏睿", "张翰 王晓晨");
Movie movie2 = new Movie(2, "上海堡垒", "2019", 2.9, "中国大陆", "爱情 战争 科幻", "滕华涛", "鹿晗 舒淇");
Movie movie3 = new Movie(3, "纯洁心灵·逐梦演艺圈", "2015", 2.2, "中国大陆", "剧情 喜剧", "毕志飞", "朱一文 李彦漫");
// 将数据存到数组中
Movie[] movies = {movie1, movie2, movie3};
MovieService movieservice = new MovieService(movies);
movieservice.start();
}
}
运行结果展示:
Java基础就到此结束:我们Java进阶见.......
s