什么是面向对象
Java的核心思想就是OOP(面向对象编程)
- 面向过程思想:
- 步骤清晰简单,第一步做什么,第二步做什么
- 处理简单问题
- 面向对象思想:
- 物以类聚,
分类
的思维方式 - 处理复杂问题
- 物以类聚,
类 = 属性 + 方法
面向对象的本质
以类的方式组织代码,以对象的形式组织(封装)数据
三大特性:
封装
继承
多态
回顾
方法的定义
1 | public class Demo01 { |
方法的调用
静态方法的调用
Student.java
1
2
3
4
5
6
7
8//学生类
public class Student {
//静态方法static
public static void say(){
System.out.println("学生说话了");
}
}Demo02.java
1
2
3
4
5public class Demo02 {
public static void main(String[] args) {
Student.say();//静态方法可以通过类名.方法名进行调用
}
}
非静态方法的调用
Student.java
1
2
3
4
5
6
7
8//学生类
public class Student {
//非静态方法static
public void say(){
System.out.println("学生说话了");
}
}Demo02.java
1
2
3
4
5
6
7
8
9public class Demo02 {
public static void main(String[] args) {
//实例化这个类 new
//对象类型 对象名 = 对象值;
Student student = new Student();
student.say();
}
}加static的方法是
和类一起加载的,时间片更早
不加static的方法是在
类实例化之后才存在
的。如果一个实例化的类或方法调用一个没有实例化的方法,则需要将该方法实例化。
通常通过new的方法来实现。
形参与实参
- 形参是参数的名字,实参是真实的值
- 实际参数与形式参数的类型要对应
类与对象的创建
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物
对象是抽象概念的具体实例
Student.java
1
2
3
4
5
6
7
8
9
10
11//学生类
public class Student {
//属性:字段
String name;
int age;
//方法
public void study(){
System.out.println(this.name+"在学习");//this表示当前类下这个学生
}
}Application.java
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//一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
//类:抽象的,实例化
//类实例化后会返回一个自己的对象!
//student对象就是一个Student类的具体实例!
Student student = new Student();
Student xiaoming = new Student();
Student xiaohong = new Student();
xiaoming.name = "小明";
xiaoming.age = 3;
xiaoming.study();
System.out.println(xiaoming.name);
System.out.println(xiaoming.age);
xiaohong.name = "小红";
xiaohong.age = 4;
System.out.println(xiaohong.name);
System.out.println(xiaohong.age);
}
}
/*输出结果:
小明在学习
小明
3
小红
4
*/
构造器详解
类中的构造器也称构造方法,是在进行创建对象的时候必须要调用的。并且构造器有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class Person {
//一个类即使什么都不写,它也会存在一个构造方法
//显示的定义构造器
String name;
//实例化
//1.使用new关键字,本质是在调用构造器
//2.用来初始化值
//无参构造
public Person(){
this.name = "秦疆";
}
//有参构造:一旦定义了有参构造,无参就必须显示定义(方法重载)
public Person(String name){
this.name = name;
//前一个name表示类中定义的字符串name
//后一个name表示传进来的参数name
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13//一个项目应该只有一个main方法
public class Application {
public static void main(String[] args) {
//new 实例化一个对象
//Person person = new Person();
Person person = new Person("狂神");
System.out.println(person.name);
}
}IDEA快捷键:
Alt
+Insert
快速定义有参或无参构造注意点:
定义有参构造之后,如果想使用无参构造,显示的定义一个无参构造
创建对象内存分析
Pet.java
1
2
3
4
5
6
7
8
9
10
11package cool.OOPS.demo3;
public class Pet {
public String name;
public int age;
//无参构造
public void shout(){
System.out.println("叫了一声");
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package cool.OOPS;
import cool.OOPS.demo3.Pet;
public class Application {
public static void main(String[] args) {
Pet dog = new Pet();
dog.name = "旺财";
dog.age = 3;
dog.shout();
System.out.println(dog.name);
System.out.println(dog.age);
Pet cat = new Pet();
}
}内存分析
小结类与对象
类与对象:
类是一个模板:抽象,对象是一个具体的实例
方法:
定义,调用!
对应的引用:
引用类型; 基本类型 (8)
对象是通过引用来操作的:栈 —> 堆
属性:字段Feild 成员变量
默认初始化:
数字:0 0.0
char: u0000
boolean: false
引用: null
修饰符 属性类型 属性名 = 属性值!
对象的创建和使用:
- 必须使用new 关键字创造对象,构造器
Person kuangshen = new Person();
- 对象的属性
kuangshen.name
- 对象的方法
kuangshen.sleep()
- 必须使用new 关键字创造对象,构造器
类:
静态的属性 属性
动态的行为 方法
封装
该露的露,该藏的藏
- 程序设计要追求“
高内聚,低耦合
”。 - 高内聚:类的内部数据操作细节自己完成,不允许外部干涉。
- 低耦合:仅暴露少量的方法给外部使用。
- 程序设计要追求“
封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,这称为信息隐藏。
记住这句话就够了:
属性私有,get/set
Demo
Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package cool.OOPS.demo4;
//类 private:私有
public class Student {
private String name;//名字
private int id;//学号
private char sex;//性别
//提供一些可以操作这个属性的方法
//提供一些public 的 get,set方法
//get获得这个数据
public String getName(){
return this.name;
}
//set给这个数据设置值
public void setName(String name){
this.name = name;
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11package cool.OOPS;
import cool.OOPS.demo4.Student;
public class Application {
public static void main(String[] args) {
Student s1 = new Student();
s1.setName("秦疆");
System.out.println(s1.getName());
}
}IDEA快捷键:
Alt
+Insert
快速生成get/set方法封装的妙用(判断数据合法性)
1
2
3
4
5
6
7
8
9
10public int getAge() {
return age;
}
public void setAge(int age) {
if (age>120 || age<0){ //不合法
this.age = 3;
}
this.age = age;
}封装的意义:
- 提高程序的安全性,保护数据。
- 隐藏代码的实现细节
- 统一接口
- 系统的可维护性提高了
继承
继承的本质是对某一类的抽象,从而实现对现实更好的建模
extends
的意思是“扩展“。子类是父类的扩展在Java中,所有的类,都默认直接或间接继承Object
Person.java
1
2
3
4
5
6
7
8package cool.OOPS.demo5;
//Person 父类,基类
public class Person {
public void say(){
System.out.println("说了一句话");
}
}Student.java
1
2
3
4
5
6package cool.OOPS.demo5;
//Student 派生类,子类
public class Student extends Person{
}Application.java
1
2
3
4
5
6
7
8
9
10package cool.OOPS;
import cool.OOPS.demo5.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
student.say();
}//说了一句话
}IDEA快捷键:
Ctrl
+H
查看当前类的树结构Java中类只有单继承,没有多继承!
一个儿子只能有一个爸爸,但是一个爸爸可以有多个儿子🤪
super详解
super注意点:
- super调用父类的构造方法,必须在构造方法的第一个!
- super必须只能出现在子类的方法或者构造方法中!
- super和this不能同时调用构造方法!
VS this:
代表的对象不同:
- this:本身调用者这个对象
- super:代表父类对象的应用
前提
- this:没有继承也可以使用
- super:只能在继承条件下才可以使用
构造方法:
- this():本类的构造
- super():父类的构造
Person.java
1
2
3
4
5
6
7
8
9
10
11
12package cool.OOPS.demo6;
public class Person {
public Person(){
System.out.println("Person无参构造执行了");
}
protected String name = "kuangshen";
//私有的东西无法被继承
public void print(){
System.out.println("Person");
}
}Student.java
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
26package cool.OOPS.demo6;
//子类继承了父类,就会拥有父类的全部的方法
public class Student extends Person{
public Student(){
//隐藏代码:调用了父类的无参构造
super(); //调用父类的构造器,必须要在子类构造器的第一行
System.out.println("Student无参构造执行了");
}
private String name = "qinjiang";
public void print(){
System.out.println("Student");
}
public void test1(){
print();//Student
this.print();//Student
super.print();//Person
}
public void test(String name){
System.out.println(name);//秦疆
System.out.println(this.name);//qinjiang
System.out.println(super.name);//kuangshen
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11package cool.OOPS;
import cool.OOPS.demo6.Student;
public class Application {
public static void main(String[] args) {
Student student = new Student();
//student.test("秦疆");
//student.test1();
}
}
方法重写
需要有继承关系,子类重写父类的方法!
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大但不能缩小:
public
>protected
>default
>private
- 抛出的异常:范围,可以缩小,但不能扩大:
ClassNotFoundException
–>Exception(大)
重写,子类的方法和父类必要一致;方法体不同!
为什么需要重写:
父类的功能,子类不一定需要,或者不一定满足!
IDEA快捷键:
Alt
+Insert
:override
;
Demo1(静态方法的重写)
B.java
1
2
3
4
5
6
7
8package cool.OOPS.demo7;
//重写都是方法的重写,和属性无关
public class B {
public static void test() {
System.out.println("B=>test()");
}
}A.java
1
2
3
4
5
6
7package cool.OOPS.demo7;
public class A extends B{
public static void test() {
System.out.println("A=>test()");
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package cool.OOPS;
import cool.OOPS.demo7.A;
import cool.OOPS.demo7.B;
public class Application {
public static void main(String[] args) {
//方法的调用只和左边,定义的数据类型有关
A a = new A();
a.test();//A=>test()
//父类的引用指向了子类
B b = new A();
b.test();//B=>test()
}
}
Demo2(非静态方法的重写)
B.java
1
2
3
4
5
6
7
8package cool.OOPS.demo7;
//重写都是方法的重写,和属性无关
public class B {
public void test() {
System.out.println("B=>test()");
}
}A.java
1
2
3
4
5
6
7
8
9
10
11package cool.OOPS.demo7;
//继承
public class A extends B{
//Override 重写
//注解:有功能的注释!
public void test() {
System.out.println("A=>test()");
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package cool.OOPS;
import cool.OOPS.demo7.A;
import cool.OOPS.demo7.B;
public class Application {
//静态的方法和非静态的方法区别很大!
//静态的方法:方法的调用只和左边,定义的数据类型有关
//非静态:重写 //必须是public类
public static void main(String[] args) {
//方法的调用只和左边,定义的数据类型有关
A a = new A();
a.test();//A=>test()
//父类的引用指向了子类
B b = new A();//子类重写了父类的方法
b.test();//A=>test()
}
}
多态
同一方法可以根据发送对象的不同而采取多种不同的行为方式
多态注意事项:
多态是方法的多态,属性没有多态
父类和子类,有联系
类型转换异常!ClassCastException!
存在条件:
继承关系
方法需要重写
父类引用指向子类对象!
Father f1 = new Son();
以下三种方法无法被重写:
static 方法,属于类,它不属于实例;
final 常量;
private 方法,私有方法;
Person.java
1
2
3
4
5
6
7package cool.OOPS.demo8;
public class Person {
public void run(){
System.out.println("run");
}
}Student.java
1
2
3
4
5
6
7
8package cool.OOPS.demo8;
public class Student extends Person{
public void run() {
System.out.println("son");
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package cool.OOPS;
import cool.OOPS.demo8.Person;
import cool.OOPS.demo8.Student;
public class Application {
public static void main(String[] args) {
//一个对象的实际类型是确定的
//可以指向的引用类型就不确定了:父类的引用指向子类
//Student能调用的方法都是自己的或者继承父类的
Student s1 = new Student();
//Person父类型,可以指向子类,但是不能调用子类独有的方法
Person s2 = new Student();
//Object类是所有类的祖宗类
Object s3 = new Student();
//对象能执行哪些方法,主要看对象左边的类型,和右边关系不大
s2.run();//son //子类重写了父类方法,执行子类方法
s1.run();//son
}
}
instanceof和类型转换
instanceof
判断两个类之间是否存在父子关系 (类型转换)引用类型,判断一个对象是什么类型~Person.java
1
2
3
4
5
6
7package cool.OOPS.demo8;
public class Person {
public void run(){
System.out.println("run");
}
}Student.java
1
2
3
4
5
6
7package cool.OOPS.demo8;
public class Student extends Person{
public void go(){
System.out.println("go");
}
}Teacher.java
1
2
3
4package cool.OOPS.demo8;
public class Teacher extends Person{
}
instanceof
Application.java
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
31package cool.OOPS;
import cool.OOPS.demo8.Person;
import cool.OOPS.demo8.Student;
import cool.OOPS.demo8.Teacher;
public class Application {
public static void main(String[] args) {
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
//System.out.println(X instanceof Y);//能不能编译通过看是否有父子关系
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof String);//false
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof Teacher);//false
//System.out.println(person instanceof String);//编译报错!
}
}
类型转换
Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16package cool.OOPS;
import cool.OOPS.demo8.Person;
import cool.OOPS.demo8.Student;
import cool.OOPS.demo8.Teacher;
public class Application {
public static void main(String[] args) {
//类型之间的转化:父 子
//高 低
Person obj = new Student();
//Student将这个对象转换为Student类型,我们就可以使用Student类型的方法了!
((Student)obj).go();//强转
}
}子类转换父类可能会丢失自己本来的一些方法
1
2
3Student student = new Student();
student.go();
Person person = student;//自动转换
- 父类引用指向子类的对象;
- 把子类转换为父类,向上转型;
- 把父类转换为子类,向下转型;强制转换
- 方便方法的调用,减少重复代码!简洁
🤔抽象:封装,继承,多态
static关键字
Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25package cool.OOPS.demo9;
//static
public class Student {
private static int age;//静态的变量 多线程!
private double score;//非静态的变量
public void run(){
}
public static void go(){
}
public static void main(String[] args) {
// Student s1 = new Student();
// System.out.println(Student.age);
// System.out.println(s1.age);
// System.out.println(s1.score);
new Student().run();
Student.go();
go();
}
}
代码块
Person.java
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
31public class Person {
//输出顺序:
//2:赋初值~
{
System.out.println("匿名代码块");
}
//1:只执行一次~
static {
System.out.println("静态代码块");
}
//3
public Person(){
System.out.println("构造方法");
}
public static void main(String[] args) {
Person person1 = new Person();
System.out.println("===============");
Person person2 = new Person();
}
}
//输出结果如下:
静态代码块
匿名代码块
构造方法
===============
匿名代码块
构造方法
静态导入包
Test.java
1
2
3
4
5
6
7
8
9
10
11
12package cool.OOPS.demo9;
//静态导入包~
import static java.lang.Math.PI;
import static java.lang.Math.random;
public class Test {
public static void main(String[] args) {
System.out.println(random());
System.out.println(PI);
}
}
抽象类
不能new抽象类,只能靠子类去实现它:约束!
抽象类中可以写普通的方法~
抽象方法必须在抽象类中~
抽象的抽象:约束~
存在意义:提高开发效率!
Action.java
1
2
3
4
5
6
7
8
9package cool.OOPS.demo10;
//abstract 抽象类:类 extends:单继承~ (接口可多继承)
public abstract class Action {
//约束~有人帮我们实现
//abstract,抽象方法,只有方法名字,没有方法的实现!
public abstract void dosomething();
}A.java
1
2
3
4
5
6
7
8
9package cool.OOPS.demo10;
//抽象类的所有方法,继承了它的子类都必须要实现它的方法~除非子类也是抽象类,就有子子类来重写它的方法
public class A extends Action{
public void dosomething() {
}
}
接口
普通类:只有具体实现
抽象类:具体实现和规范(抽象方法)都有!
接口:只有规范!自己无法写方法~专业的约束!约束和实现分离:面向接口编程
接口的本质是契约
,就像我们人间的法律一样。制定好后大家都遵守。OO的精髓,是对对象的抽象,最能体现这一点的就是接口。
声明类的关键字是class,声明接口的关键字是interface
UserService.java
1
2
3
4
5
6
7
8
9
10
11
12
13package cool.OOPS.demo11;
//interface 定义的关键字,接口都需要有实现类
public interface UserService {
//常量~ public static final
int AGE = 99;
//接口中的所有定义的方法其实都是抽象的 public abstract
void add(String name);
void delete(String name);
void update(String name);
void query(String name);
}TimeService.java
1
2
3
4
5package cool.OOPS.demo11;
public interface TimeService {
void timer();
}UserServiceImpl.java
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
33package cool.OOPS.demo11;
//抽象类:extends~
//类 可以实现接口 implements 接口
//实现了接口的类,就需要重写接口中的方法~
//多继承~ 利用接口实现多继承~
public class UserServiceImpl implements UserService,TimeService{
public void add(String name) {
}
public void delete(String name) {
}
public void update(String name) {
}
public void query(String name) {
}
public void timer() {
}
}作用:
- 约束
- 定义一些方法,让不同的人实现~
- public abstract
- public static final
- 接口不能被实例化
,接口中没有构造方法 - implements可以实现多个接口
- 必须要重写接口中的方法~
内部类
内部类就是在一个类的内部再定义一个类。
比如:A类中定义一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类了。
分类:
- 成员内部类
- 静态内部类
- 局部内部类
- 匿名内部类
Outer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package cool.OOPS.demo12;
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{ //加static即为静态内部类,那么getID方法将无法使用,因为static时间片更早
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性~
public void getID(){
System.out.println(id);
}
}
}Application.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14package cool.OOPS;
import cool.OOPS.demo12.Outer;
public class Application {
public static void main(String[] args) {
Outer outer = new Outer();
//通过这个外部类来实例化内部类~
Outer.Inner inner = outer.new Inner();
inner.in();
inner.getID();
}
}匿名内部类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19package cool.OOPS.demo12;
public class Outer {
private int id = 10;
public void out(){
System.out.println("这是外部类的方法");
}
public class Inner{
public void in(){
System.out.println("这是内部类的方法");
}
//获得外部类的私有属性~
public void getID(){
System.out.println(id);
}
}
}