点击勘误issues (opens new window),哪吒感谢大家的阅读
# 面向对象
- 基本概念
- 类和对象
- 构造方法
- this和super的用法
- 对象数组
- 对象间的关系
- 封装
- 继承
- 多态
- static
- final
- 修饰符的作用范围
- 抽象类
- 接口
- 内部类
# 面向对象概述
程序发展:非结构化程序设计-》结构化程序设计-》面向对象程序设计
类和对象
# 类的定义
package ...;
// Person:用于描述整个人类的公共特征
// 一个类由两个部分来组成:人类的静态特征(属性),人类的动态行为(方法)
// 先定义类,再由类来创建对象
public class Person {
String name;
int age;
public void speak() {
System.out.println("会说话");
}
public void walk() {
System.out.println("会走路");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 创建对象
// 创建一个人出来
Person p = new Person();
p.name = "张三"
p.age = 20;
// 方法也是通过对象,来调用
p.desc();
Person p2 = new Person();
p2.desc();
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 无参构造方法
构造方法:如果一个类中没有写任何构造方法,则默认有无参的构造方法。
构造方法是一种特殊的方法
- 写法上:名称和类名必须一致,没有返回值类型
- 作用上:用于创建对象
public class Person {
String name;
int age;
public Person() {
System.out.println("我是无参构造方法");
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 有参构造方法
// 一般方法也是属于具体某个对象的
// 构造方法:
// 1.如果一个类中没有写任何构造方法,则默认有无参的构造方法。
// 2.如果提供了其他构造方法,则默认的无参构造不再提供
// 构造方法是一种特殊的方法
// 1. 写法上:名称和类名必须一致,没有返回值类型
// 2. 作用上:用于创建对象
pubic class Person {
String name;
int age;
public Person() {
// System.out.println("我是无参构造方法")
}
public Person(String n) {
name = n;
}
public Person(String n, int a) {
name = n;
age = a;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package ...
public class Test {
public static void main(String[] args) {
Person p = new Person("张三", 20);
p.desc();
Person p2 = new Person("李四");
p2.age = 20;
p2.desc();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
重载:
- 方法名相同,方法参数不同,称为方法的重载
- 方法参数不同,参数个数不同,类型不同,顺序不同
# 构造方法的相互调用
// this(参数) 表示对本类其他构造方法的调用
public class Person {
String name;
int age;
public Person() {
this("张三", 20);
}
public Person(String n) {
name = n
}
// 全参构造
public Person(String n, int a) {
// this(n)
name = n;
age = a;
}
public void speak() {
// ...
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package ...;
public class Test {
public static void main(String[] args) {
// Person p = new Person("张三", 20);
// p.desc();
Person p = new Person();
p.desc();
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
构造方法的相互调用问题:要避免死循环
- this(参数)表示对本类其他构造方法的调用
- this. 来调用本类的属性 或 方法
public class Person {
String name;
int age;
public Person() {}
public Person(String n) { name = n }
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# this用法理解
# 对象数组的使用
# 对象间的关系
package ...;
public class Person {
String name;
int age;
Person child;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
pubic Person(String name, int age, Person child) {
this.name = name;
this.age = age;
this.child = child;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 引用传递
public class Test {
public static void main(String[] args) {
// 引用存在于栈中,对象存在于堆中
Person p = new Person("张三", 20);
Person p2 = p;
// new: 用于开辟堆内存空间,创建对象
p2 = new Person("李四", 20);
System.out.println(p.name); // 张三
System.out.println(p2.name); // 李四
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 封装
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
if(age<0){
this.age = 0;
}else{
this.age = age;
}
}
public void desc() {
System.out.println("")
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package ...;
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.setAge(-20);
System.out.println(p.getAge());
Person p2 = new Person("李四", -20);
p2.desc();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
package ...;
public class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name
}
public void setName(String name) {
this.name = name
}
public int ageAge() {
return age
}
public void setAge(int age) {
this.age = age;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 完全封装
- 属性全部私有
- 提供统一的访问方式
- 提供无参和全参构造
- 实现序列化接口
# 封装后的对象间关系
# 封装练习
- 电商购物项目 Java类Goods, 然后创建Goods对象并赋值为以下值。
goodsId: 商品编号
goodsName: 商品中文名
goodsEnglishName: 商品英文名
goodsThumb: 商品缩略图下载地址
goodsImg: 商品大图下载地址
addTime: 商品上架时间,单位
1
2
3
4
5
6
2
3
4
5
6
# Goods.java
public class Goods {
private long goodsId;
private String goodsName;
private String goodsEnglishName;
private String goodsThumb;
private String goodsImg;
// 强制类型转换 或者 使用大范围的类型
private long addTime = 133435400000L;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# TestTime.java
package ...;
public class Test {
public static void main(String[] args) {
// 当前时间距离1970年1月1号0:0:0时间差的毫秒值
long l = System.currentTimeMillis();
System.out.println(l);
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
基本数据类型:
- 整数:byte(1) short(2) int(4) long(8)
- 浮点型:float, double
- 布尔类型:boolean
- 字符类型:char
引用数据类型:类,接口,数组,枚举等
完全封装:1.属性全部私有;2.提供get和set;3.提供无参和全参构造;4.实现序列化接口
package ...;
public class Circle {
private double r;
private Point point;
// 2*r
public double getC() {
return 2*Math.PI*this.r;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Point p1 = new Point(2,3);
Point p2 = new Point(3,4);
double d = p1.getDistance(p2);
1
2
3
2
3
# 继承
使用extends关键字
public class Person {
private String name;
private int age;
public Person() {}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void desc() {
System.out.println(name+":"+age);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
student
// student
public class Student extends Person {
private String sno;
public String getSno() {
return sno;
}
public void setSno(String sno) {
this.sno = sno;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# super
super:指向父类对象
使用super(参数)调用父类的构造方法
super.setName(name);
// student继承自person
public class Student extends Person {
public Student() {
super();
}
public Student(String name, int age, String sno) {
// super();
super(name, age);
this.sno = sno;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 重写
- 发生在父子类之间
- 同名同参同返回
override
# 单根继承即Object的理解
# toString的重写
java.lang
类 Object
java.lang.Object
public class Object
类Object是类层次结构的根类。每个都使用Object作为超类。所有对象都实现这个类的方法。
1
2
3
4
5
2
3
4
5
# hashcode 和 equals 的重写
# 多态
多态,一个表现,两条定理
- 当发生多态时,引用只能调用父类的方法,不能调用子类的方法。
- 当发生多态时,如果调用的方法子类进行了重写,则会调用子类重写之后的方法。
# 多态的理解
编译,运行
# 多态中的类型转换
public class Test {
public static void main(String[] args) {
Animal d = new Dog();
d.eat();
if (d instanceof Dog) {
Dog d2 = (Dog)d;
d2.dogMethod();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 使用多态的好处
# 抽象方法 和 抽象类
public abstract double getTotalSal();
1
如果一个类中有抽象方法,则该类必须声明为抽象的,如果不声明为抽象的,则必须重写父类的所有抽象方法。
package ...;
public class A extends Emp {
@Override
public double getTotalSal() {
return this.getSal()*12+1
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# abstract 总结说明
package ...;
public abstract class Emp {
private int id;
private String name;
private double sal;
public Emp() {
super();
}
public Emp(int id, String name, double sal) {
super();
this.id = id;
this.name = name;
this.sal = sal;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
abstract: 抽象的
- 如果一个类中有抽象方法,则该类必须声明为抽象的,如果不声明为抽象的,则必须重写父类的所有抽象方法。
抽象方法:
- 不知道具体该写什么,就写成抽象的,让子类去自己定义(重写)就可以。
- 抽象方法是一种标准,强制要求非抽象子类必须重写。
抽象类:
- 抽象类中可以有非抽象方法,也可以有抽象方法,或者只有其一。
# 抽象类 和 接口
接口
- 接口不是类,只是可以看作是一种特殊的抽象类
- 类和类是继承关系,是单继承关系,接口和类是实现关系,接口和接口之间是继承关系,并且是多继承关系
- 接口没有构造方法和抽象类一样,只能通过子实现类通过多态来调用
JDK1.8之前:
- 接口中所有的方法,都是public abstract 修饰的抽象方法。
- 接口中所有的字段(属性)都是public static final修饰的常量。
# static
# final
final: 不可变的,最终的
- 修饰属性,表示必须给属性赋值,并且该属性的值不能再变化。和static修饰的属性称为不可变的变量(常量)
- 修饰方法,表示该方法不能被重写。
- 修饰类,表示该类不能继承,那么所有的方法都不能被重写。
- 修饰局部变量。
# 成员内部类 和 静态内部类
内部类:
- 可以共用一些数据
- 该类只在它所在的外部类中使用
成员内部类,静态内部类,局部内部类,匿名内部类
# 匿名内部类
# 内部类使用练习
package ...;
import javax.swing.JFrame;
public class MyFrame extends JFrame {
public MyFrame() {
setBounds(200, 200, 200, 300);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new MyFrame();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 面向对象总结
对象分类 产生 类,考虑类的安全和方便,有了封装;为了代码复用,有了继承;父子类才能有重写,重写是多态的前提。