目标读者
了解 Java 基本数据类型
掌握 Java 输出、for、if 等基本语法
熟练应用函数,了解函数重载等基本知识
熟练使用 IntelliJ IDEA
权限修饰符
类、成员变量、成员方法最前面的单词叫做权限修饰符,表明从项目的哪些地方可以访问这个类、变量、方法。具体见下表:
是否能访问 | 同一文件 | 同一包 | 子类 | 不同类 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | |
default(缺省) | √ | √ | ||
private | √ |
举例:
类:老师(Teacher)
特征:成员变量:有姓名(name),年龄(age)等属性
行为:成员方法:讲课(teaching)、布置作业(assignWork)
Class(类)
语法规则:
// public class xxx
// xxx 自己给类取的名字
public class Teacher{
// 成员变量
String name;
int age;
// 构造方法 --- 获得对象的方法
// 与类同名,无返回值
// 在用该类实例化一个对象的时候需要被调用
// 类默认自带无参构造函数
Teacher(){
}
// 有参构造函数
// 一般是为成员变量赋值
Teacher(String name){
......
}
// 普通成员方法
private void teaching(){
......
}
void assignWork(){
......
}
}
思考:
1.teaching是否可以获得值 name 或者 age?
根据变量的作用域可知,是可以的。
举例:
有一个老师,她叫twter,年龄是18岁
有一个老师,她叫冠中,年龄是5岁
有一个老师,她叫昕姐,年龄是3岁
对象
对象是描述客观事物的一个实体,由类实例化来生成。
普通的成员变量和成员方法都是属于这个对象的。
即这个对象诞生,属于这个对象的成员变量和成员方法才诞生。
要通过对象才能获得成员变量和成员方法。
构造方法
构造方法是类与对象的桥梁,构造方法和类同名,且没有返回值。
在构造方法内可以进行成员变量的赋值。
通过new调用构造方法可以获得类的实例化对象。
public class Teacher {
// 成员变量
String name;
int age;
// 构造方法
// 默认自带无参
Teacher() {
}
Teacher(String mname,int mage){
name = mname;
age = mage;
}
}
public class Test {
public static void main(String[] args) {
// 通过new可以生成一个新的具体的类
// 我们称之为实例化 Teacher 生成一个 Teacher 的对象
Teacher teacher = new Teacher();
Teacher teacher1 = new Teacher();
// teacher 和 teacher1 不是同一个对象
teacher.name = "twter";
teacher.age = 18;
// 执行构造函数内的语句,进行赋值
// Teacher的实例化对象 teacher3
// teacher3的name是twter,age是18
Teacher teacher2 = new Teacher("twter", 18);
Teacher teacher3 = new Teacher("greenTea", 12);
}
}
思考:
1.如何获得一个老师,她叫绿茶,年龄是12岁。
2.有参构造函数可以写成如下形式吗?
public class Teacher {
// 成员变量
String name;
int age;
Teacher(String name,int age){
name = name;
age = age;
}
}
this
代表“当前对象”示例
就可以区别传入的参数“name”和对象自己的“name”。
public class Teacher {
// 成员变量
String name;
int age;
Teacher(String name,int age){
this.name = name;
this.age = age;
}
}
举例:
某个老师上课(teaching)的时候会说 name 老师在上课
成员方法
public class Teacher {
// 成员变量
String name;
int age;
Teacher(String name){
this.name = name;
}
Teacher(String name, int age) {
this.name = name;
this.age = age;
}
// 普通成员方法
void teaching() {
System.out.println(name + "is teaching");
}
}
public class Test {
public static void main(String[] args) {
Teacher teacher2 = new Teacher("twter", 18);
Teacher teacher3 = new Teacher("sxbasubx");
teacher2.teaching();
}
}
思考:
1.某个老师布置作业(assingWork)的时候会说老师布置了 x 道作业
public class Teacher {
// 成员变量
String name;
int age;
Teacher(String name, int age) {
this.name = name;
this.age = age;
}
void assignWork(int x) {
System.out.println(name + " assign " + x + " number of homework");
}
}
public class Test {
public static void main(String[] args) {
Teacher teacher2 = new Teacher("twter", 18);
teacher2.assignWork(2);
}
}
2.如何保护 name 不被随意修改?
public class Teacher {
// 成员变量
private String name;
}
但是我在main函数里想要获得老师对象的 name?
public class Teacher {
// 成员变量
private String name;
public String getName() {
return name;
}
}
封装
要访问该类的代码和数据,必须通过严格的接口控制。
外部可以修改name,比如在main函数里可以修改name,但是必须按照规定的方式来。
public class Teacher {
// 成员变量
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
疑惑:那这和我直接用 public 修饰 name 变量有什么区别呐?
课堂作业
类:小饼干(cookie)
这个小饼干是由巧克力和抹茶组成的!
成员变量:价格(price),小饼干中巧克力的价格(priceOfChocolate),小饼干中抹茶的价格(priceOfTea)
price = priceOfChocolate + priceOfTea
我想要在main函数里实例化3个不同价格的巧克力和不同价格抹茶的组成的小饼干对象。
Coockie | priceOfChocolate | priceOfTea |
---|---|---|
coockie1 | 12.4 | 121 |
coockie2 | 13 | 423 |
Coockie3 | 12937 | 1213.2 |
根据 price 理解封装的好处。
想要统计生成的饼干数量?
这个信息应该是凌驾于对象上的
static
用static修饰的成员变量和成员方法不再依赖于对象,而是属于类本身。可以直接通过类名获得
1.静态方法里可以使用静态成员变量吗?
2.普通(非静态)方法里可以使用静态成员变量吗?
3.普通方法里可以使用普通成员变量吗?
4.静态方法里可以使用普通成员变量吗?
5.普通方法里可以调用静态方法吗?
6.静态方法里可以调用静态方法吗?
7.静态方法里可以调用普通方法吗?
yes yes yes no yes yes no
package xyz.chenshuyusc.course2;
public class Coockie {
private double price;
private double priceOfChocolate;
private double priceOfTea;
private static int count; // = 0
public Coockie() {
++count;
}
public Coockie(double priceOfsth, boolean isTea) {
if (isTea) {
this.priceOfTea = priceOfsth;
} else {
this.priceOfChocolate = priceOfsth;
}
this.price = this.priceOfTea;
++count;
}
public Coockie(double priceOfTea){
this.priceOfTea = priceOfTea;
this.price = this.priceOfTea;
}
public double getPrice() {
return price;
}
public double getPriceOfChocolate() {
return priceOfChocolate;
}
public double getPriceOfTea() {
return priceOfTea;
}
public void setPriceOfChocolate(double priceOfChocolate) {
this.priceOfChocolate = priceOfChocolate;
this.price = this.priceOfChocolate + this.priceOfTea;
}
public void setPriceOfTea(double priceOfTea) {
this.priceOfTea = priceOfTea;
this.price = this.priceOfChocolate + this.priceOfTea;
}
public static int getCount() {
return count;
}
protected void setPrice(double price) {
this.price = price;
}
}
举例子:
类:甜甜的小饼干
这个小饼干是由巧克力和抹茶组成的甜味小饼干!
成员变量:价格(price),小饼干中巧克力的价格(priceOfChocolate),小饼干中抹茶的巧克(priceOfTea),糖(priceOfSugar)
类:咸咸的小饼干
这个小饼干是由巧克力和抹茶组成的咸味小饼干!
成员变量:价格(price),小饼干中巧克力的价格(priceOfChocolate),小饼干中抹茶的巧克(priceOfTea),盐(priceOfYan)
看起来和之前的小饼干很重合!!!
extends ( 继承 )
子类继承父类的特征和行为。
即甜甜的小饼干继承小饼干,就获得了小饼干中非private的成员变量和成员方法。
但甜甜的小饼干又比小饼干多了priceOfSugar。
public class Coockie {
private double price;
private double priceOfChocolate;
private double priceOfTea;
public Coockie() {
}
public Coockie(double priceOfsth, boolean isTea) {
if (isTea) {
this.priceOfTea = priceOfsth;
} else {
this.priceOfChocolate = priceOfsth;
}
this.price = this.priceOfTea;
}
public double getPrice() {
return price;
}
public double getPriceOfChocolate() {
return priceOfChocolate;
}
public double getPriceOfTea() {
return priceOfTea;
}
public void setPriceOfChocolate(double priceOfChocolate) {
this.priceOfChocolate = priceOfChocolate;
this.price = this.priceOfChocolate + this.priceOfTea;
}
public void setPriceOfTea(double priceOfTea) {
this.priceOfTea = priceOfTea;
this.price = this.priceOfChocolate + this.priceOfTea;
}
protected void setPrice(double price) {
this.price = price;
}
}
public class SugarCoockie extends Coockie {
private double priceOfSugar;
public SugarCoockie(double priceOfsth, boolean isTea) {
super(priceOfsth,isTea);
}
public double getPriceOfSugar() {
return priceOfSugar;
}
public void setPriceOfSugar(double priceOfSugar) {
setPrice(getPrice() - this.priceOfSugar + priceOfSugar);
this.priceOfSugar = priceOfSugar;
}
}
子类的构造方法必须调用父类的构造方法。
思考:如果要通过子类实例化对象,父类可以没有构造函数吗?
Override
子类中包含跟父类方法签名一样的方法,父类的方法会被覆盖掉,我们就说该方法被重写。如需调用父类原有的成员方法,可使用 super 关键字。
public class Coockie {
protected double price;
protected double priceOfChocolate;
protected double priceOfTea;
public Coockie() {
}
public Coockie(double priceOfsth, boolean isTea) {
if (isTea) {
this.priceOfTea = priceOfsth;
} else {
this.priceOfChocolate = priceOfsth;
}
this.price = this.priceOfTea;
}
public double getPrice() {
return price;
}
public double getPriceOfChocolate() {
return priceOfChocolate;
}
public double getPriceOfTea() {
return priceOfTea;
}
public void setPriceOfChocolate(double priceOfChocolate) {
this.priceOfChocolate = priceOfChocolate;
this.price = this.priceOfChocolate + this.priceOfTea;
}
public void setPriceOfTea(double priceOfTea) {
this.priceOfTea = priceOfTea;
this.price = this.priceOfChocolate + this.priceOfTea;
}
public static int getCount() {
return count;
}
protected void setPrice(double price) {
this.price = price;
}
}
public class SugarCoockie extends Coockie {
private double priceOfSugar;
@Override
public void setPriceOfChocolate(double priceOfChocolate) {
this.priceOfChocolate = priceOfChocolate;
this.price = this.priceOfSugar + this.priceOfChocolate + this.priceOfTea;
}
@Override
public void setPriceOfTea(double priceOfTea) {
super.setPriceOfTea(priceOfTea);
this.price = this.priceOfSugar + this.priceOfChocolate + this.priceOfTea;
}
public double getPriceOfSugar() {
return priceOfSugar;
}
public void setPriceOfSugar(double priceOfSugar) {
this.priceOfSugar = priceOfSugar;
this.price = this.priceOfSugar + this.priceOfChocolate + this.priceOfTea;
}
}
Builder 设计模式
当一个类需要初始化的成员变量比较多、比较复杂时,仅使用构造方法来初始化对象就显得冗余且难以理解,这里介绍一个经典的解决办法:利用 Builder 设计模式实现链式调用来获取对象。
package xyz.chenshuyusc.course2;
public class Coockie {
double price;
double priceOfChocolate;
double priceOfTea;
Choc choc = new Choc();
public Coockie() {
}
public Coockie(double priceOfChocolate, double priceOfTea,Choc choc) {
this.choc = choc;
this.priceOfTea = priceOfTea;
this.priceOfChocolate = priceOfChocolate;
this.price = this.priceOfTea + this.priceOfChocolate;
}
public double getPrice() {
return price;
}
public double getPriceOfChocolate() {
return priceOfChocolate;
}
public double getPriceOfTea() {
return priceOfTea;
}
public void setPriceOfChocolate(double priceOfChocolate) {
choc.price = priceOfChocolate;
this.priceOfChocolate = priceOfChocolate;
this.price = this.priceOfChocolate + this.priceOfTea;
}
public void setPriceOfTea(double priceOfTea) {
this.priceOfTea = priceOfTea;
this.price = this.priceOfChocolate + this.priceOfTea;
}
}
public class CoockieBuilder {
private Coockie coockie = new Coockie();
public CoockieBuilder priceOfTea(double priceOfTea) {
coockie.setPriceOfTea(priceOfTea);
return this;
}
public CoockieBuilder priceOfChocolate(double priceOfChocolate) {
coockie.setPriceOfChocolate(priceOfChocolate);
return this;
}
}
package xyz.chenshuyusc.course2;
public class TestCoockie {
public static void main(String[] args) {
Coockie coockie = new CoockieBuilder()
.priceOfChocolate(1213)
.priceOfTea(1293)
.build();
CoockieBuilder coockieBuilder = new CoockieBuilder();
coockieBuilder = coockieBuilder.priceOfTea(1231.2);
coockieBuilder = coockieBuilder.priceOfChocolate(21);
coockieBuilder = coockieBuilder.priceOfTea(213);
System.out.println(coockie.getPriceOfChocolate());
System.out.println(coockie.getPriceOfTea());
System.out.println(coockie.getPrice());
}
}