Java学习笔记-Day4

Part5:面向对象编程

什么是面向对象

面向对象编程(Object-Oriented Programming, OOP)

面向对象编程的本质就是:以类的方式组织代码,以对象的方式封装数据。

从现实的角度:先有对象,再有类。对象是具体的事物,类是对对象的抽象。

从代码的角度:先有类,再有对象。类是抽象的模板,对象是类具体的实例。

类的基本构成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
修饰符 class 类名{ //类名一般用大写字母开头
// 属性:静态的属性
修饰符 属性类型 属性名 = 属性值;

// 方法:动态的行为;构造器(构造方法:与类名相同的方法)默认自动生成
// 构造器
修饰符 类名(){
// 用于类的初始化
}
// 其他方法
修饰符 返回值类型 方法名(){
// 代码块
return ...;
}

}

类与对象的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 学生类
public class Student {
// 属性:字段
String name; //null
int age; //0

// 静态方法,通过类名可以直接调用:Student.study()
public static String study() {
return "学习~";
}

// 非静态方法,需先实例化对象,通过对象调用
/*
Student student = new Student();
student.sleep();
*/
public String sleep() {
return "睡觉~";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {

//类是抽象的,需要先实例化
//类实例化后会返回一个自己的对象!
//xiaoming对象就是一个Student类的具体实例!
Student xiaoming = new Student();
Student xiaohong = new Student();

xiaoming.name = "小明";
xiaoming.age = 10;

System.out.println(xiaoming.name);
System.out.println(xiaoming.age);

xiaohong.name = "小红";
xiaohong.age = 11;

System.out.println(xiaohong.name);
System.out.println(xiaohong.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
package com.zhou.oop.Demo05;

// 学生类
public class Student {
// 属性:字段
String name; //null
int age; //0


// 静态方法,通过类名可以直接调用:Student.study()
public static String study() {
return "学习~";
}

// 非静态方法,需先实例化对象,通过对象调用
/*
Student student = new Student();
student.sleep();
*/
public String sleep() {
return "睡觉~";
}
}

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
36
37
38
39
40
41
42
43
package com.zhou.oop;

import com.zhou.oop.Demo05.Student;

import java.io.IOException;

// 方法的定义和调用
public class Demo01 {
// main方法
public static void main(String[] args) {
int max = max(10, 10);
System.out.println(max);

// 静态方法,通过类名可以直接调用:Student.study()
String s1 = Student.study();
System.out.println(s1);

// 非静态方法,需先实例化对象,通过对象调用
Student student = new Student();
String s2 = student.study();
System.out.println(s2);
}

/*
修饰符 返回值类型 方法名(...){
// 方法体
return 返回值;
}
*/
public String sayHello() {
return "Hello World";
}

public static int max(int a, int b) {
return a>b ? a:b;
}

// 抛出异常
public void readFile(String file) throws IOException{

}
}

方法的重载

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
36
37
38
39
40
41
42
package com.zhou.oop;

// 方法的重载
// 方法名相同,但参数不同
public class Demo02 {
public static void main(String[] args) {
double max = max(20, 10);
System.out.println(max);
}

// 比大小
public static int max(int num1, int num2) {
int result = -1;

if (num1 > num2) {
result = num1;
System.out.println("num1>num2");
} else if (num1 == num2) {
System.out.println("num1==num2");
return 0;
} else {
result = num2;
}

return result;
}

public static double max(double num1, double num2) {
double result = 0;

if (num1 > num2) {
result = num1;
} else if (num1 == num2) {
System.out.println("num1==num2");
return 0;
} else {
result = num2;
}
return result;
}
}

可变参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.zhou.oop;

// 可变参数(不定项参数)
// 在方法声明中,在指定参数类型后加一个省略号(...)
// 一个方法中只能有一个可变参数,它必须是方法的最后一个参数。
public class Demo03 {
public static void main(String[] args) {
Demo03 demo03 = new Demo03();
demo03.test(1,2,3,4,5,6);
}

public void test(int...i){
for (int j = 0; j < i.length; j++) {
System.out.println(i[j]);
}
}


}

递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.zhou.oop;

// 递归
public class Demo04 {
public static void main(String[] args) {
int s = f(4);
System.out.println("10!="+s);
}

public static int f(int n){
if(n==1){
return 1;
}else {
return n*f(n-1);
}
}
}

构造器详解

使用new关键字创建对象时,除了分配内存空间外,还会给创建好的对象进行默认的初始化,以及对类中构造器的调用。

类中的构造器也称为构造方法,是在进行创建对象时必须要调用的。并且构造器有以下两个特点:

  1. 必须和类的名字相同
  2. 必须没有返回类型,也不能写void
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
package com.zhou.oop.Demo05;

public class Person {

//一个类即使什么都不写,也会默认存在一个方法,即构造器

String name;
int age;

//显示定义一个构造器
//1. 使用new关键字,本质是在调用构造器
//2. 用来初始化值
public Person(){
// 实例化初始值
this.name = "guiyi";
}

//有参构造:一旦定义了有参构造,无参构造就必须显示定义

public Person(String name, int age) {
this.name = name;
this.age = age;
}


// alt+insert快捷键 生成有参构造器
}

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
36
package com.zhou.oop.Demo05;

// 一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {

//类是抽象的,需要先实例化
//类实例化后会返回一个自己的对象!
//xiaoming对象就是一个Student类的具体实例!
Student xiaoming = new Student();
Student xiaohong = new Student();

xiaoming.name = "小明";
xiaoming.age = 10;

System.out.println(xiaoming.name);
System.out.println(xiaoming.age);

xiaohong.name = "小红";
xiaohong.age = 11;

System.out.println(xiaohong.name);
System.out.println(xiaohong.age);

System.out.println("===================================");

Person person = new Person();
System.out.println(person.name);

Person zhangfei = new Person("张飞",13);
System.out.println(zhangfei.name);
System.out.println(zhangfei.age);
}
}


封装、继承和多态

封装(数据的隐藏)

通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。

封装的好处:

  1. 提高程序的安全性,保护数据
  2. 隐藏代码的实现细节
  3. 统一接口
  4. 系统可维护性增加了

概况一句话就是:属性私有,get/set

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
package com.zhou.oop.Demo05;

public class Teacher {
// 属性私有
private String name;
private int age;

// get/set 快捷键:alt+insert

public String getName() {
return name;
}

public int getAge() {
return age;
}

public void setName(String name) {
this.name = name;
}

// 通过封装,使用set可以帮助判断参数设置的合理性
public void setAge(int age) {
if (age>=0 && age<=120){
this.age = age;
}else{
System.out.println("年龄错误");
};
}
}

1
2
3
4
5
6
7
8
9
10
package com.zhou.oop.Demo05;

// 一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.setAge(130);
System.out.println(teacher.getAge());
}
}

继承和多态

继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。

继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.zhou.oop.Demo05;

public class Person {

// 开放权限从大到小:public > protected > default > private
public String name;
protected int age; // 继承树中的类可以使用
char sex; // default
private int money = 1000_000_000;
public double height = 1.7;

public Person(){
System.out.println("Person无参构造执行了");
}

public int getMoney() {
return money;
}

public void setMoney(int money) {
this.money = money;
}
}

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
package com.zhou.oop.Demo05;

// ctrl + H 查看继承树
// object类是所有类共同的祖先
public class Teacher extends Person{

private double height = 1.9;
private String subject;

public Teacher(){
// 隐藏代码:调用了父类的无参构造
// this()和super()不能同时调用,因为他们都要放在构造器里第一行!
super(); // 调用父类的构造器,必须放在子类构造器的第一行
//this("语文"); // 调用自己的有参构造
System.out.println("Teacher无参构造执行了");
}

public Teacher(String subject){
this.subject = subject;
}

public void teach(){
System.out.println("教你学java~");
}

// 比较this、super
public void test(double height){
System.out.println(height); // 方法传递过来的参数
System.out.println(this.height); // 当前类下的height属性:1.9
System.out.println(super.height); // 父类中的height属性:1.7
}

}

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
package com.zhou.oop.Demo05;

// 一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
Teacher teacher = new Teacher();
teacher.name = "zhou";
teacher.age = 20;
teacher.sex = '1';
// teacher.money; // 报错,私有属性无法被继承!!

// 通过方法调用父类中的私有属性
System.out.println(teacher.getMoney());

teacher.test(1.5);
}
}

/*
输出内容:

Person无参构造执行了
Teacher无参构造执行了
1000000000
1.5
1.9
1.7

*/


super注意点:

  1. super()调用父类的构造方法,必须在子类构造方法中的第一行,且不能和this()同时调用
  2. super.方法super.属性必须只能出现在子类的方法或构造方法中

多态

Java的方法调用总是作用于运行期对象的实际类型,这种行为称为多态

一个对象的实际类型是确定的,但可以指向对象的引用类型有很多(父类,有关系的类)。

多态存在的条件

  1. 有继承关系
  2. 子类重写父类的方法
  3. 父类引用指向子类对象

注意:多态是方法的多态,属性没有多态性

方法的重写

重写都是方法的重写,跟属性无关!

重写需要有继承关系,子类重写父类的方法!

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大但不能缩小(privatefinal无法被重写): public > Protected > Default > private
  4. 抛出的异常:范围可以被缩小,但不能扩大:ClassNotFoundException(小) --> Exception(大)

为什么需要重写:

  1. 父类的功能,子类不一定需要,或者不一定满足
1
2
3
4
5
6
7
8
9
package com.zhou.oop.Demo05;

public class B {

public void test() {
System.out.println("B=>test()");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.zhou.oop.Demo05;

public class A extends B{

// @Override 重写
/*
注意:
1. 只能重写不带static关键字的非静态方法
因为static静态方法是类的方法,可通过类名直接调用,而不需要通过对象调用
2. 重写的方法关键字不能为
*/
public void test() {
System.out.println("A=>test()");
}
}

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
package com.zhou.oop.Demo05;

// 一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
A a = new A();

// 父类的引用指向了子类
// 方法的调用只和左边(即定义的数据类型)有关
// Java的方法调用总是作用于运行期对象的实际类型,这种行为称为多态
B b = new A();

System.out.println("static静态方法无法被重写");
a.test1();
b.test1();

// 父类的方法被子类重写,执行子类的方法
System.out.println("父类方法被子类重写后:");
a.test2();
b.test2();
}
}

/*
输出结果:

static静态方法无法被重写
A=>test()
B=>test()
父类方法被子类重写后:
A=>test()
A=>test()

*/

抽象类和接口

抽象类

abstract修饰符可以用来修饰方法,也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。

抽象类中可以没有抽象方法,但抽象方法的类一定要声明为抽象类。

抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。

抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。

子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类。

1
2
3
4
5
6
7
package com.zhou.oop;

// abstract 抽象类:类 extend:单继承 (接口可以多继承)
public abstract class Demo06 {
public abstract void doSomething();
}

接口

普通类:只有具体实现

抽象类:具体实现和规范(抽象方法)都有!

接口:只有规范!

接口就是规范,定义的是一组规则。

声明类的关键字是class,声明接口的关键字是interface

1
2
3
4
5
6
7
8
9
10
11
12
package com.zhou.oop.demo07;

public interface UserService {

// 接口中的所有定义的方法其实都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);

}

Part6:异常处理

异常包括:抛出异常、捕获异常

异常处理五个关键字:try, catch, finally, throw, throws

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
36
package com.zhou.exception;

public class Demo01 {
public static void main(String[] args) {
new Demo01().test(1,0);
}

public void test(int a, int b){
if (b==0){
throw new ArithmeticException(); // 主动抛出异常,一般在方法中
}
}
}

// try catch finally
/*
public static void main(String[] args) {

int a = 1;
int b = 0;

// 假设要捕获多个异常:从小到大!
// 快捷键:ctrl + alt + t
try { // try监控区域
System.out.println(a / b);
} catch (Error e) { // catch(想要捕获的异常类型) 捕获异常
System.out.println("Error");
} catch (Exception e) {
System.out.println("Exception");
} catch (Throwable t) {
System.out.println("Throwable");
} finally { // finally可以不要,用于处理善后工作
System.out.println("finally");
}
}
*/
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2024 归一
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信