目录
1.设计对象
什么是面向对象呢,顾名思义,首先你要先有个对象,然后要面向对象,然后才能解决问题(
那么既然你没有对象,如何设计对象呢?
首先对象是什么呢:
对象就是你的女朋友(不是),对象可以是一台电脑,一辆汽车,一个人,你的女朋友(一本正经),而这些对象都有属性,比如大小、颜色、年龄等等,同样可以定义行为,如移动。
那如何设计对象呢:
首先要定义一个类,然后在类里面定义属性。说了这么多,不如演示一下。下面我定义一个人类。
package com.zwcode.object;
public class Test01 {
public static void main(String[] args) {
//这样我的女朋友(一个人 类)就定义出来了
People myGirlFriend = new People();
myGirlFriend.name = "小仙女";
myGirlFriend.age = 18;//永远18岁
myGirlFriend.run();
}
}
//类名-我的女朋友
class People{
//姓名
String name;
//年龄
int age;
//可以定义行为如跑步
public void run(){
System.out.println(name + "在跑步");
}
}
定义完人这个类后就可以new出一个对象,这里就是我的女朋友,我可以定义她的姓名年龄等等,运行结果如下:
小仙女在跑步
同样的,定义完一个人类后,不仅能new出我的女朋友,还可以new出别的人,比如第二个女朋友(不是),比如你的父母老师等等都可以,只要是人就可以。
下面再new出一个人并给出一些定义
//再定义一个人
People myTeacher = new People();
myTeacher.name = "张麻子";
myTeacher.age = 46;
myTeacher.run();
运行结果
小仙女在跑步
张麻子在跑步
在定义类时,需要注意的几点:
2.内存机制
值得注意的是:局部变量存在栈中,其中s1也是局部变量也叫引用;new出来的对象存在堆内存中,它的地址赋给在栈中的引用部分。
3.面向对象实战:购物车案例
需求:模拟购物车模块的功能,需要实现添加商品到购物车中去,同时需要提供修改商品的购买数量,结算商品价格功能。
分析:购物车中每个商品都是一个对象,需要定义一个商品类;购物车本身也是一个对象,可以使用数组代表它;完成界面结构,让用户选择操作的功能。
- 添加商品:add
- 查看商品:query
- 修改数量:update
- 结算价格:pay
请您选择要操作的功能:
代码如下:
package com.itzw.practice;
import java.util.Scanner;
public class ShopCarTest {
public static void main(String[] args) {
//创建一个购物车,可以存放100个商品
Goods[] shopCar = new Goods[100];
while (true){
//菜单
System.out.println("添加商品到购物车:add");
System.out.println("查看购物车的商品:query");
System.out.println("修改购物车商品数量:update");
System.out.println("结算购物车商品价格:pay");
System.out.println("请您选择要操作的功能:");
//开始选择功能
Scanner sc = new Scanner(System.in);
String commend = sc.next();
switch (commend) {
case "add":
//添加商品
addShop(shopCar, sc);
break;
case "query":
//查看商品
queryShop(shopCar);
break;
case "update":
//修改数量
updateShop(shopCar, sc);
break;
case "pay":
//结算价格
payShop(shopCar);
break;
default:
System.out.println("输入错误,请重新输入!");
break;
}
}
}
public static void payShop(Goods[] shopCar) {
//总价格
double sum = 0;
for (int i = 0; i < shopCar.length; i++) {
if (shopCar[i] != null){
sum += shopCar[i].price * shopCar[i].buyNumber;
}else{
break;
}
}
System.out.println("购物车商品总价格为:" + sum);
}
public static void updateShop(Goods[] shopCar, Scanner sc) {
while (true){
System.out.println("请输入要修改的商品的编号:");
int id = sc.nextInt();
Goods g = getGoodsById(shopCar,id);
if (g == null){
System.out.println("找不到该商品!");
}else{
System.out.println("请输入需要修改该商品的数量:");
int updateNumber = sc.nextInt();
g.buyNumber = updateNumber;
queryShop(shopCar);
break;
}
}
}
//根据编号得到商品对象
public static Goods getGoodsById(Goods[] shopCar, int id){
for (int i = 0; i < shopCar.length; i++) {
if (shopCar[i] == null)
return null;
else{
if (shopCar[i].id == id)
return shopCar[i];
}
}
return null;
}
public static void queryShop(Goods[] shopCar) {
System.out.println("购物车商品如下:");
System.out.println("=======================");
System.out.println("编号\t\t\t名称\t\t\t价格\t\t\t数量");
for (int i = 0; i < shopCar.length; i++) {
//要先判断对象是否为空
if (shopCar[i] == null)
break;
else
System.out.println(shopCar[i].id+"\t\t\t"+shopCar[i].name+"\t\t\t"
+shopCar[i].price+"\t\t\t"+shopCar[i].buyNumber);
}
}
public static void addShop(Goods[] shopCar, Scanner sc) {
//输入编号
System.out.println("请输入编号:");
int id = sc.nextInt();
//输入名称
System.out.println("请输入名称:");
String name = sc.next();
//输入价格
System.out.println("请输入价格:");
double price = sc.nextDouble();
//输入购买数量
System.out.println("请输入数量:");
int buyNumber = sc.nextInt();
//创建一个商品对象
Goods g = new Goods();
g.id = id;
g.name = name;
g.price = price;
g.buyNumber = buyNumber;
//把新创建的对象存入购物车
//存入前要判断购物车下标,是否已经被使用
for (int i = 0; i < shopCar.length; i++) {
if (shopCar[i] == null) {
shopCar[i] = g;
break;
}
}
System.out.println("添加成功!");
}
}
class Goods {
int id;//编号
String name;//名称
double price;//价格
int buyNumber;//购买数量
}
本次案例知识模拟购物车,很多东西都没有考虑,日后再完善。
4.构造器、this
4.1构造器
构造器的作用:用于初始化一个类的对象,并返回对象的地址
构造器格式:如下展示了构造器的格式,分为有参和无参
- 无参构造:初始化对象时成员变量采用默认值。
- 有参构造:在初始化对象时,同时可以接受参数对变量赋值。
class Student{
String name;
int age;
//无参构造
public Student(){
System.out.println("无参构造执行了。。。");
}
//有参构造
public Student(String n, int a){
System.out.println("有参构造执行了。。。");
name = n;
age = a;
}
}
下面演示一下无参构造和有参构造的区别,在main方法中输入以下代码
public static void main(String[] args) {
//创建s1对象用无参构造
Student s1 = new Student();
System.out.println(s1.name + " " + s1.age);
//创建s2对象用有参构造
Student s2 = new Student("张麻子",45);
System.out.println(s2.name + " " + s2.age);
}
运行结果:
无参构造执行了。。。
null 0
有参构造执行了。。。
张麻子 45
从结果可以发现,和前面说到的结论一样。
值得注意的是:
- 任何类定义出来,默认就自带了无参构造器,写不写都有
- 一旦定义了有参构造器,name无参构造器就没有了,如果还想用无参构造器,此时就需要自己手写一个无参构造器了。
- 建议大家在创建好类时,之间就无脑写上有参和无参构造器,写上总是没错的。
4.2 this
this是什么:this代表了当前对象的地址。这个知识点很关键!
下面用代码演示一下
public class Test01 {
public static void main(String[] args) {
Car car = new Car();
car.run();
System.out.println(car);
}
}
public class Car {
public Car(){
System.out.println("午餐构造的this" + this);
}
public void run(){
System.out.println("方法中的this" + this);
}
}
运行得到的结果:我们发现三处的this结果是一样的,都是当前对象的地址。
午餐构造的thiscom.itzw.thisdemo.Car@1b6d3586
方法中的thiscom.itzw.thisdemo.Car@1b6d3586
com.itzw.thisdemo.Car@1b6d3586
this的作用:用于指定访问当前对象的成员变量、成员方法。
怎么理解这个作用呢,在上面我们写到有参构造时,参数名最好是能和成员变量名一样,这样更方便理解,但是又不能写一样的,这样编译器就不好理解了,它分辨不出此时的变量名是参数还是当前对象的变量,给有参构造赋值就会失败。这时this就派上了用处,因为this是用于访问当前对象的,话不多说,下面演示一下。
package com.itzw.thisdemo;
public class Test02 {
public static void main(String[] args) {
Student s1 = new Student("马邦德",45);
System.out.println(s1.name + " " + s1.age);
s1.friend("张麻子");
}
}
class Student{
String name;
int age;
public Student() {
}
//有参构造
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void friend(String name){
System.out.println(this.name + "是" + name + "的朋友");
}
}
运行结果:
马邦德 45
马邦德是张麻子的朋友
如果去掉this,结果必然是错误的,可自行演示一下
5.封装
什么是封装:
- 告诉我们,如何正确设计对象的属性和方法。
- 原则:对象代表什么,就得封装对应的数据,并提供数据对应的行为。
好处:
- 让编程变得简单,有什么事,找对象,掉方法就行。
- 降低学习成本,不用记对象的那么多方法有需要时去找就行。
- 建议每次定义好类的成员变量时就立刻封装。
下面演示一下封装:
package com.itzw.fengzhuang;
public class Test01 {
public static void main(String[] args) {
Person p1 = new Person();
p1.setAge(100);
System.out.println(p1.getAge());
}
}
class Person{
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
if (age >= 0 && age <= 150){
this.age = age;
}else{
System.out.println("您输入的年龄有误");
}
}
}
这样我们就不能随意修改年龄,只能通过set方法修改,并且可以在set方法里面做限制,本次限制年龄在0-150之间,若超过这部分则提示出错,会输出默认值0。
6.JavaBean
JavaBean也称为实体类,其对象可用于在程序中封装数据
标准JavaBean需满足如下书写要求:
- 成员变量使用private修饰。
- 提供成员变量对应的set和get方法。
- 必须提供一个无参构造器;有参构造器可以不写。
代码演示:
package com.itzw.javabean;
public class Test01 {
public static void main(String[] args) {
}
}
class User{
private String name;//姓名
private double heigth;//身高
private double salary;//薪水
public User() {
}
public User(String name, double heigth, double salary) {
this.name = name;
this.heigth = heigth;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHeigth() {
return heigth;
}
public void setHeigth(double heigth) {
this.heigth = heigth;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
以上就是标准JavaBean,我们发现,这其实就是前面学到的构造器和封装的结合,我们在写类时,建议写成这种形式。
下面使用一下标准JavaBean:
public class Test01 {
public static void main(String[] args) {
//使用无参构造
User user1 = new User();
user1.setName("张麻子");
user1.setHeigth(180);
user1.setSalary(1000);
System.out.println(user1.getName());
System.out.println(user1.getHeigth());
System.out.println(user1.getSalary());
//使用有参构造
User user2 = new User("马邦德",179,10000);
System.out.println(user2.getName());
System.out.println(user2.getHeigth());
System.out.println(user2.getSalary());
}
}
7.成员变量和局部变量
成员变量:
- 在类中,方法外
- 有默认值,无需初始化
- 在堆内存中
- 随着对象的创建而存在,随着对象的消失而消失
- 作用域无法确定,在类外创建对象就可以访问,在类内也可以访问
局部变量:
- 常见于方法中
- 没有默认值,使用之前要赋值
- 在栈内存中
- 随着方法的调用而存在在,随着方法的运行结束而消失
- 作用域为在所属的大括号中
8.案例
模仿电影信息展示
package com.itzw.demo;
public class MovieTest {
public static void main(String[] args) {
//创建三个电影对象,封装信息
Movie m1 = new Movie("长津湖",9.8,"吴京");
Movie m2 = new Movie("斗牛",8.8,"黄渤");
//定义一个电影数组,存放三部电影
Movie movies[] = new Movie[3];
movies[0] = m1;
movies[1] = m2;
//也可以直接在后面new一个对象,不需要先new再存入,这样更方便
movies[2] = new Movie("无人区",9.9,"徐峥");
//输出电影信息
for (int i = 0; i < movies.length; i++) {
System.out.println("名称:" + movies[i].getName());
System.out.println("评分:" + movies[i].getScore());
System.out.println("主演:" + movies[i].getActor());
System.out.println("================================");
}
}
}
class Movie{
private String name;
private double score;
private String actor;
public Movie() {
}
public Movie(String name, double score, String actor) {
this.name = name;
this.score = score;
this.actor = actor;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public String getActor() {
return actor;
}
public void setActor(String actor) {
this.actor = actor;
}
}
输出结果:
名称:长津湖
评分:9.8
主演:吴京
================================
名称:斗牛
评分:8.8
主演:黄渤
================================
名称:无人区
评分:9.9
主演:徐峥
================================