以下为个人学习笔记和习题整理
课程:面向对象程序设计 ——Java 语言
- 浙江大学 - 翁恺 @ 中国大学 MOOC
https://www.icourse163.org/course/ZJU-1001542001
# 课堂笔记
# 用类制造对象
对象是实体,需要被创建,可以为我们做事情
类是规范,根据类的定义来创建对象
对象(这只猫)
表达东西或事件
运行时响应消息(提供服务)类(猫)
定义所有猫的属性
就是 Java 中的类型
可以用来定义变量
graph TD | |
A[类] --> |定义了|B[对象] | |
B --> |是...的实体|A |
对象 = 属性 + 服务
数据:属性或状态
操作:函数
把数据和对数据的操作放在一起 ➡️ 封装
new VendingMachine(); | |
VendingMachine v= new VendingMachine() |
对象变量是对象的管理者
v.insertMoney(10); | |
v.getFood(); |
.
运算符让对象做事
# 成员变量和成员函数
- 成员变量:类定义的对象中所具有的变量。
每个对象有自己的变量,和同一个类的其他对象是分开的。
在函数中可以直接写成员变量的名字来访问成员变量。
函数是通过对象来调用的。
如 v.insertMoney()
让 insertMoney()
内部的成员变量指的是 v
的成员变量。
this
是成员函数的一个特殊的固有的本地变量,它表达了调用这个函数的那个对象。
通过 .
运算符调用某个对象的函数。
在成员函数内部直接调用自己 this
的其他函数,不需要额外加 this.
。
成员变量的生存期是对象的生存期,作用域是类内部的成员函数。
写在类里的成员变量,只是一个声明,变量并不在那里,变量不在类里,变量在每一个对象里。
- 本地变量:定义在函数内部的变量。
本地变量的生存期和作用域都是函数内部。
# 对象初始化
Java 提供了多种手段来保障对象创建时的初始化,包括给每个成员变量默认的 0
值、定义初始化和构造函数。
# 成员变量定义初始化
- 成员变量在定义的地方就可以给出初始值
- 没有给出初始值的成员变量会自动获得
0
值 - 对象变量的
0
值表示没有管理任何对象,也可以主动给null
值 - 定义初始化可以调用函数,甚至可以使用已经定义的成员变量
# 构造函数
与类同名,没有返回值类型。
# 函数重载
一个类可以有多个构造函数,只要它们的参数表不同
创建对象的时候,给出不同的参数值,就会自动调用不同的构造函数
一个类里的同名,但参数表不同的函数构成了重载关系
通过 this()
还可以调用其他构造函数,但是只能调用无参数构造函数,且只能放在构造函数内的第一句,只能调用一次。
# 课内项目
# 画形状
package shapes; | |
public class MyPic { | |
public static void main(String[] args) | |
{ | |
Picture pic = new Picture(1000,1000); | |
Circle c1 = new Circle(500,500,260); | |
Circle c2 = new Circle(500,500,250); | |
Circle c3 = new Circle(500,500,125); | |
Triangle t1 = new Triangle(500, 250, 283, 625, 716, 625); | |
Triangle t2 = new Triangle(500, 750, 283, 375, 716, 375); | |
pic.add(c1); | |
pic.add(c2); | |
pic.add(c3); | |
pic.add(t1); | |
pic.add(t2); | |
pic.draw(); | |
} | |
} |
package shapes; | |
import java.awt.Graphics; | |
import java.util.ArrayList; | |
import javax.swing.JFrame; | |
import javax.swing.JPanel; | |
public class Picture extends JFrame { | |
private static final long serialVersionUID = 1L; | |
private int width; | |
private int height; | |
private ArrayList<Shape> listShape = new ArrayList<Shape>(); | |
private class ShapesPanel extends JPanel { | |
private static final long serialVersionUID = 1L; | |
@Override | |
protected void paintComponent(Graphics g) { | |
super.paintComponent(g); | |
for ( Shape s : listShape ) | |
{ | |
s.draw(g); | |
} | |
} | |
} | |
public void add(Shape s) | |
{ | |
listShape.add(s); | |
} | |
public Picture(int width, int height) | |
{ | |
add(new ShapesPanel()); | |
this.setDefaultCloseOperation(EXIT_ON_CLOSE); | |
this.width = width; | |
this.height = height; | |
} | |
public void draw() | |
{ | |
setLocationRelativeTo(null); | |
setSize(width, height); | |
setVisible(true); | |
} | |
} |
package shapes; | |
import java.awt.Graphics; | |
public abstract class Shape { | |
public abstract void draw(Graphics g); | |
} |
package shapes; | |
import java.awt.Graphics; | |
public class Circle extends Shape { | |
private int x; | |
private int y; | |
private int radius; | |
public Circle(int x, int y, int radius) | |
{ | |
this.x = x; | |
this.y = y; | |
this.radius = radius; | |
} | |
@Override | |
public void draw(Graphics g) { | |
g.drawOval(x-radius, y-radius, radius*2, radius*2); | |
} | |
} |
package shapes; | |
import java.awt.Graphics; | |
public class Line extends Shape { | |
private int x1; | |
private int y1; | |
private int x2; | |
private int y2; | |
public Line(int x1, int y1, int x2, int y2) | |
{ | |
this.x1 = x1; this.y1 = y1; | |
this.x2 = x2; this.y2 = y2; | |
} | |
@Override | |
public void draw(Graphics g) { | |
g.drawLine(x1, y1, x2, y2); | |
} | |
} |
package shapes; | |
import java.awt.Graphics; | |
public class Rectangle extends Shape { | |
private int x; | |
private int y; | |
private int width; | |
private int height; | |
public Rectangle(int x, int y, int width, int height) { | |
this.x = x; | |
this.y = y; | |
this.width = width; | |
this.height = height; | |
} | |
@Override | |
public void draw(Graphics g) { | |
g.drawRect(x, y, width, height); | |
} | |
} |
package shapes; | |
import java.awt.Graphics; | |
public class Triangle extends Shape { | |
private int[] x = new int[3]; | |
private int[] y = new int[3]; | |
public Triangle(int x1, int y1, int x2, int y2, int x3, int y3) | |
{ | |
x[0] = x1; x[1] = x2; x[2] = x3; | |
y[0] = y1; y[1] = y2; y[2] = y3; | |
} | |
@Override | |
public void draw(Graphics g) { | |
g.drawPolygon(x, y, x.length); | |
} | |
} |
# 自动售货机
public class VendingMachine { | |
int price = 80; | |
int balance = f(); | |
int total; | |
VendingMachine() // 构造函数 | |
{ | |
total = 0; | |
} | |
VendingMachine(int price) // 函数重载 | |
{ | |
this(); // 位于第一行,调用无参数构造函数 | |
this.price = price; | |
} | |
int f() | |
{ | |
return 10; | |
} | |
void showPrompt() | |
{ | |
System.out.println("Welcome"); | |
} | |
void insertMoney(int amount) | |
{ | |
balance = balance + amount; | |
} | |
void showBalance() | |
{ | |
System.out.println(balance); | |
// System.out.println(this.balance); | |
} | |
void getFood() | |
{ | |
if (balance >= price) | |
{ | |
System.out.println("Here you are."); | |
balance = balance - price; | |
total = total + price; | |
} | |
} | |
public static void main(String[] args) { | |
VendingMachine vm = new VendingMachine(); | |
vm.showPrompt(); | |
vm.showBalance(); | |
vm.insertMoney(100); | |
vm.getFood(); | |
vm.showBalance(); | |
VendingMachine vm1 = new VendingMachine(100); | |
vm1.insertMoney(200); | |
vm.showBalance(); | |
vm1.showBalance(); | |
} | |
} |
# 课堂讨论
函数重载与类型自动转换
在零基础学 Java 中曾经提到过一个类型自动转换的事情。就是如果一个地方,比如函数的参数需要的是比较宽的类型的数据,比如double
就比int
来得宽,那么如果调用函数的时候给出了int
值,是会被自动转换成double
去调用函数的。现在,如果有两个函数重载,一个是
double
,一个是int
,还会发生类型自动转换吗?写一个测试程序来试一下,告诉大家结果吧。
存在两个重载函数并不会发生类型自动转换,程序会自动寻找对应的重载函数
只存在一个比较窄的数据类型的重载函数时,程序会报错
只存在一个比较宽的数据类型的重载函数时,程序会自动转换
import java.util.Scanner; | |
public class Main { | |
public static class Test { | |
Test(double digit){ | |
System.out.println ( digit ); | |
} | |
Test(int digit){ | |
System.out.println ( digit ); | |
} | |
} | |
public static void main(String[] args) { | |
Scanner input = new Scanner ( System.in ); | |
Test t0 = new Test ( input.nextInt () ); | |
} | |
} |