目录
1. 概述
- 找/设计对象来解决问题
- 类:具有共同属性的对象,是一个抽象的概念。
比如:汽车、人、狗、神; - 对象:真实存在的具体实例,是类的实例化。
比如:推土车是汽车的实例化;姚明是人的实例化;小白(狗的名字)是狗的实例化;二郎神是神的实例化; - 属性:描述具体某个对象的特征,是静态的。
比如:姚明身高2.6米多;小白的毛发是棕色的;二郎神额头上有只眼睛; - 方法:每个对象有它们自己的行为或者是使用它们的方法,是动态的。可以使用方法来操作一个对象;
比如:一只狗会跑会叫等,我们把这些行为称之为方法 - 类的成员:属性和方法称为这个对象的成员,因为它们是构成一个对象的主要部分,没有了这两样东西,那么对象也没什么存在意义了。
2. 设计对象
2.1 格式
- 设计类
public class 类名{
1、成员属性(变量,一般是名词)
2、成员方法(行为,一般是动词)
3、构造器(后面学)
4、代码块(后面学)
5、内部类(后面学)
} - 实例化对象
类名 对象名 = new 类名(); - 访问对象
对象名.成员属性 //访问变量
对象名.方法名() //访问行为
//示例
// 设计类
public class Car {
// 属性
String name;
double price;
// 方法
public void start(){ }
public void run(){ }
}
// 实例化对象
public class CarTest {
public static void main(String[] args) {
// 如何实例化对象
Car carA = new Car();
// 如何使用对象
carA.name = "carA";
carA.price = 10000;
System.out.println(carA.name + ": "+ carA.price);
carA.start();
carA.run();
System.out.println("----------");
// 如何实例化对象
Car carB = new Car();
// 如何使用对象
carB.name = "carB";
carB.price = 50000;
System.out.println(carB.name + ": " + carB.price);
carB.start();
carB.run();
}
}
- 注意事项
- 类名首字母大写,驼峰格式
- 一个Java文件中,可以定义多个class类,但只有一个是public修饰。将public修饰的类名作为文件名。(建议一个代码文件定义一个class类)
- 成员属性的完整定义格式:
修饰符 数据类型 变量名 = 初始值
,一般无需默认值。
byte short char int long 默认值0
float double 默认值0.0
boolean 默认值false
类 接口 数组 String 默认值null
public class ClassAttention {
// 1 类名首字母大写,驼峰格式
// 2 一个Java文件中,可以定义多个class类,但只有一个是public修饰。将public修饰的类名作为文件名。(建议一个代码文件定义一个class类)
// 3 成员属性的完整定义格式:`修饰符 数据类型 变量名 = 初始值`,一般无需默认值。
public static void main(String[] args) {
Car carDefault = new Car();
System.out.println(carDefault.name); //null
System.out.println(carDefault.price); //0.0
}
3. 内存机制
3.1 内存
方法区:字节码文件加载时进入
栈内存:方法运行时进入;变量
堆内存:new的对象会在堆内存中开辟空间并产生地址。
3.2 示例
- 对象存储在堆内存中
Car carA = new Car();
的变量名carA存储的是对象在堆内存中的地址。- 成员属性(变量)的数据存放在对象中,在堆内存中。
- 两个对象的内存图:
5:两个变量指向一个对象的内存图
3.3 垃圾回收
- 如上例,如果
s1 = null
,s2 = null
,则变量s1
和s2
存储的堆内存的地址为null,不能再指向堆内存对象。 - 没有变量引用堆内存中的对象,即为垃圾对象。
- Java存在自动垃圾回收期,会定期清理
4. 构造器
4.1 构造器的作用
- 定义在类中的, 可以用于初始化一个类的对象,井返回对象的地址。eg:Car C = new Car()
4.2 构造器格式
- 方法名与类名相同,大小写也要一致
- 没有返回值类型,连void都没有
- 没有具体的返回值(不能由retrun带回结果数据)
- 定义格式
修饰符 类名(形参列表){
…
}
-
调用格式
类 变量名称 = new 构造器;
-
示例
- 定义
public class Car {
String name;
double price;
/*
无参数构造器
*/
public Car(){
System.out.println("无参数构造器");
}
/*
有参数构造器
*/
public Car(String n, double p){
name = n;
price = p;
System.out.println("有参数构造器");
}
}
- 调用
public static void main(String[] args) {
//无参数构造器 默认存在,初始化对象时,成员变量的数据均采用默认值。
Car c = new Car();
System.out.println(c.name);
System.out.println(c.price);
c.name = "奔驰";
c.price = 39.8;
System.out.println(c.name);
System.out.println(c.price);
//有参数构造器:初始化对象时,同时可以接受参数为对象进行赋值。
Car c1 = new Car("奔驰",39.8);
System.out.println(c1.name);
System.out.println(c1.price);
}
- 分类和作用
- 无参数构造器:默认存在,初始化对象时,成员变量的数据均采用默认值。
- 有参数构造器:初始化对象时,同时可以接受参数为对象进行赋值。
4.5. 注意事项
- 任何类定义出来,默认就自带了无参数构造器,写不写都有。
- 一旦定义了有参数构造器,那么无参数构造器就没有了。如果还想用无参数构造器,此时需要写一个无参数构造器。
5. this关键字
5.1 简介
this关键字:可以出现在构造器方法中;代表当前对象的地址。
作用:可以用于指定访问当前对象的成员变量,成员方法。
5.2 示例
- 定义
/*
this 关键字的作用
*/
public class Car {
public Car(){
System.out.println("无参数构造器的this:" + this);
}
public void run(){
System.out.println("方法的this:" + this);
}
}
- 调用
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.run();
System.out.println(c);
}
}
//无参数构造器this:stu.javase.day6.thisdemo.Car@6cd8737
//方法的this:stu.javase.day6.thisdemo.Car@6cd8737
//stu.javase.day6.thisdemo.Car@6cd8737
- 作用
public class Car {
String name;
double price;
//成员变量
public Car(String name, double price) {
this.name = name;
this.price = price;
System.out.println("有参数构造器的this:" + this);
}
//成员方法
public void goWith(String name){
System.out.println(this.name + "正在和" + name + "比赛!");
}
}
public class Test {
public static void main(String[] args) {
//成员变量
Car c1 = new Car("奔驰",39.8);
System.out.println(c1.name);
System.out.println(c1.price);
//成员方法
c1.goWith("宝马");
}
}
6. 封装
6.1 定义
- 封装:如何正确设计对象的属性和方法
- 原则:对象代表什么,就要封装对应的数据,并提供数据对应的行为。
- 例如:人画圆:人(变量,方法)& 圆(变量:半径,方法:画圆);
人关门:人(变量,方法)& 门(变量,方法:关门); - 优点:目前已经有很多都封装成相应的对象,使用时直接调用对象方法即可。比如String代表字符串对象,拥有很多操作字符串的方法;Socket代表网络连接,可以连接别人,收发消息。
6.2 如何封装
- 一般建议对成员变量使用private关键字修饰,private修饰的成员只能在当前类中访问。
- 为每个成员变量提供配套 public修饰的的getter、setter方法暴露其取值和赋值。
- 示例
// 学生类
/*
封装
*/
public class Student {
//1. 对成员变量使用private关键字修饰,private修饰的成员只能在当前类中访问。
private int age;
// 构造函数
public Student(){
}
//构造函数
public Student(int age){
this.age = age;
}
// 2. 为每个成员变量提供配套 public修饰的的getter、setter方法暴露其取值和赋值。
public void setAge(int age){
if (age > 0 && age < 200){
this.age = age;
}
else{
System.out.println("请检查年龄是否有误!");
}
}
public int getAge(){
return age;
}
}
// 测试类
public class Test {
public static void main(String[] args) {
Student s = new Student(10);
System.out.println(s.getAge());
s.setAge(18);
System.out.println(s.getAge());
}
}
7. 标准JavaBean
7.1 JavaBean
- 可以成为实体类,对象可以用于在程序中封装数据。
- 标准JavaBean书写要求:
- 成员变量使用private修饰;
- 提供成员变量对应的setXxx()/getXxx()方法;
- 必须提供一个无参构造器;有参数构造器是可写可不写的;
7.2 示例
用户类
public class User {
// 1. 成员变量使用private修饰;
private String name;
private double height;
private double salary;
/*
3.必须提供一个无参构造器;有参数构造器是可写可不写的;
*/
public User() {
}
public User(String name, double height, double salary) {
this.name = name;
this.height = height;
this.salary = salary;
}
/*
2. 提供成员变量对应的setXxx()/getXxx()方法;
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
测试类
public class Test {
public static void main(String[] args) {
// 无参数构造器
User u1 = new User();
u1.setName("lll");
u1.setHeight(1.60);
u1.setSalary(10000.0);
System.out.println("姓名:" + u1.getName() + ";身高(m):" + u1.getHeight() + ";工资(元):" + u1.getSalary());
// 姓名:lll;身高(m):1.6;工资(元):10000.0
//有参数构造器
User u2 = new User("zzz", 1.65, 15000.0);
System.out.println("姓名:" + u2.getName() + ";身高(m):" + u2.getHeight() + ";工资(元):" + u2.getSalary());
// 姓名:zzz;身高(m):1.65;工资(元):15000.0
}
}
8. 补充:成员变量/局部变量
- 对比
9. 综合案例
9.1 购物车模块
- 需求
模拟购物车模块的功能,需要实现添加商品到购物车中去,同时需要提供修改商品的购买数量,结算商品价格功能。 - 分析
- 购物车中的每个商品都是一个对象,需要定义一个商品类。
- 购物车本身也是一个对象:可以使用数组对象代表它。
- 完成界面架构,让用户选择操作的功能。
- 实现
- 商品类
package stu.javase.day6.shopcart;
public class Goods {
int id; //编号
String name; //名称
double price; //价格
int buyNum; //购买数量
}
- 购物车类
package stu.javase.day6.shopcart;
import java.util.Scanner;
public class ShopCartTest {
public static void main(String[] args) {
// 1.定义商品类,用于后期创建商品对象
// 2. 定义购物车对象,使用数组表示。(数组固定长度,有不足。后期会使用集合表示)
Goods[] shopCar = new Goods[100]; //默认值null
queryGoods(shopCar);
boolean flag = true;
while (flag) {
// 3. 搭建架构
System.out.println("*****请选择如下命令进行操作*****");
System.out.println("--添加商品到购物车:add--");
System.out.println("--查询购物车的商品:query--");
System.out.println("--修改商品购买数量:update--");
System.out.println("--结算商品购买金额:pay--");
System.out.println("--退出:exit--");
Scanner sc = new Scanner(System.in);
System.out.println("请你输入命令:");
String command = sc.next();
switch (command){
case "add":
addGoods(shopCar, sc);
break;
case "query":
queryGoods(shopCar);
break;
case "update":
updateGoods(shopCar, sc);
break;
case "pay":
payGoods(shopCar);
break;
case "exit":
flag = false;
System.out.println("*****购物结束,欢迎下次再来*****");
break;
default:
System.out.println("没有该功能,请重新输入!");
break;
}
}
}
/*
添加商品功能
*/
public static void addGoods(Goods[] shopCar, Scanner sc){
//1. 录入用户输入的商品信息
System.out.print("请输入商品编号:");
int id;
while (true){
int id_input = sc.nextInt(); //编号
boolean flag = true; //编号不重复
for (int i = 0; i < shopCar.length; i++) {
if (shopCar[i] != null) {
if (shopCar[i].id == id_input){
flag = false;
break;
}
}else break;
}
if (flag){
id = id_input;
break;
}
}
System.out.print("请输入商品名称:");
String name = sc.next(); //名称
System.out.print("请输入商品数量:");
int buyNum = sc.nextInt(); //购买数量
System.out.print("请输入商品价格:");
double price = sc.nextDouble(); //价格
// 2. 将商品信息封装为一个商品对象
Goods g = new Goods();
g.id = id;
g.name = name;
g.buyNum = buyNum;
g.price = price;
// 3. 添加进购物车
for (int i = 0; i < shopCar.length; i++) {
//shopCar = [g1, g2, g3, …… null, null……]
if (shopCar[i] == null){
shopCar[i] = g;
break;
}
}
System.out.println("您的商品"+ g.name +"已添加!");
}
/*
查询购物车商品
*/
public static void queryGoods(Goods[] shopCar){
System.out.println("======购物车清单======");
System.out.println("编号\t\t名称\t\t数量\t\t价格");
for (int i = 0; i < shopCar.length; i++) {
//shopCar = [g1, g2, g3, …… null, null^]
if (shopCar[i] != null){
System.out.println(shopCar[i].id + "\t\t" + shopCar[i].name +
"\t\t" + shopCar[i].buyNum + "\t\t" + shopCar[i].price);
}else{
// 遍历结束
break;
}
}
}
/*
更新购物车商品数量
*/
public static void updateGoods(Goods[] shopCar, Scanner sc){
// 商品信息
queryGoods(shopCar);
while (true) {
System.out.print("输入增加商品数量的编号:");
int id = sc.nextInt();
Goods g = findIdGoods(shopCar, id);
// 返回商品
if (g != null) {
System.out.print("请重新输入商品数量:");
int buyNum = sc.nextInt();
g.buyNum = buyNum;
break;
}
//没有商品
else{
System.out.print("请重新输入商品编号:");
}
}
}
/*
查询id对应商品
*/
public static Goods findIdGoods(Goods[] shopCar, int id){
for (int i = 0; i < shopCar.length; i++) {
if (shopCar[i] != null) {
if(id == shopCar[i].id){
System.out.println("编号:" + shopCar[i].id + "\t名称" + shopCar[i].name +
"\t数量" + shopCar[i].buyNum + "\t价格" + shopCar[i].price);
return shopCar[i];
}
}else{
System.out.println("未查询到该编号对应商品!");
break;
}
}
return null;
}
/*
为商品付款
*/
public static void payGoods(Goods[] shopCar){
queryGoods(shopCar);
int pay = 0;
for (int i = 0; i < shopCar.length; i++) {
if (shopCar[i] != null){
pay += shopCar[i].price * shopCar[i].buyNum;
}
else break;
}
System.out.println("付款:" + pay);
}
}
9.2 电影信息展示
-
需求
使用java,模仿电影信息展示
-
分析
- 一部电影是一个Java对象,需要先设计电影类,再创建电影对象。
- 三部电影对象可以采用数组存储起来。
- 依次遍历数组中的每个电影对象,取出其信息进行展示。
电影类
public class Movie {
// 1. 成员变量
private String name;
private String country;
private double score;
private String director;
private String actor;
// 3. constructor
public Movie() {
}
public Movie(String name, String country, double score, String director, String actor) {
this.name = name;
this.country = country;
this.score = score;
this.director = director;
this.actor = actor;
}
// 2. get set
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
}
测试类
public class Test {
public static void main(String[] args) {
// 1. 设计电影类
// 2. 实例化3个对象
// 3. 定义一个电影类型的数组,实例化每个数组对象
Movie[] movies = new Movie[3];
movies[0] = new Movie("《长津湖》","china",7.7,"徐克","吴京");
movies[1] = new Movie("《我和我的父辈》","china",7.8,"吴京","吴京");
movies[2] = new Movie("《五个扑水的少年》","china",5.9,"宋灏霖","王川");
// 4. 遍历数字输出电影信息
for (int i = 0; i < movies.length; i++) {
System.out.println("----------------------------------------------------");
System.out.println("电影名:" + movies[i].getName() + "\t国家:" +movies[i].getCountry() + "\t评分:" + movies[i].getScore() + "\t导演:" + movies[i].getDirector() + "\t主演:" + movies[i].getActor());
}
}
}
/*
----------------------------------------------------
电影名:《长津湖》 国家:china 评分:7.7 导演:徐克 主演:吴京
----------------------------------------------------
电影名:《我和我的父辈》 国家:china 评分:7.8 导演:吴京 主演:吴京
----------------------------------------------------
电影名:《五个扑水的少年》 国家:china 评分:5.9 导演:宋灏霖 主演:王川
*/