Java面向对象编程
面向对象编程 OOP
面向对象编程: Object-Oriented Programming,以类的形式组织代码,以对象的形式组织封装数据
从认识论的角度考虑,先有对象后有类。对象是具体的;类是抽象的
从代码运行的角度考虑,先有类后有对象。类是对象的模板这里是引用
类
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但不能代表某一个具体的事物
对象
对象是抽象概念的具体实例
类和对象的创建
运行结果:
构造方法 (构造器)
一个类即使什么都不写,也会存在一个构造方法,他有以下两个特点:
- 必须和类的名字相同
- 必须没有返回类型,也不能写void
有参构造和无参构造
定义有参构造时,必须先写无参构造
运行结果:
Alt + Insert
快速生成构造器
三大特性
封装
当类的属性设置为private
时,就不能直接查询和修改了,需要一些属性方法 get / set
实现
意义
- 提高程序安全性,保护数据
- 隐藏代码实现细节
- 统一接口
- 增加系统可维护性
继承
继承是类
和类
之间的一种关系,除此之外,还有依赖、组合、聚合 等
实现
子类可以继承父类的全部方法和属性,私有的属性无法继承 可以通过get/set方法
运行结果:
Object类
在类中 Ctrl + H
显示继承树
在Java中所有的类都默认直接或间接的继承Object类
Object类中有许多方法。。。
super
属性
运行结果:
方法
运行结果:
无参构造
子类无参构造时会默认调用父类的无参构造
运行结果:
调用父类的构造器必须在子类构造器的第一行
注意点
super
调用父类的构造方法,必须在构造方法的第一个super
必须只能出现在子类的方法或者构造中方法中super
和this
不能同时调用构造方法
对比 this
- 代表对象不同
this
本身调用者这个对象super
代表父类对象的应用
- 使用前提
this
没有继承也可以使用super
只能在继承条件中使用
- 构造方法
this()
本类的构造super()
父类的构造
方法重写
静态方法
运行结果:
非静态方法
运行结果:
注意点
- 重写需要有继承关系,子类重写父类的方法
- 方法名必须相同
- 参数类别必须相同
- 修饰符范围可以扩大不能缩小
public > protected > Default > private
- 抛出的异常的范围可以缩小不能扩大
Exception > ... > ClassNotFoundException
重写子类的方法和父类的必须要一直;方法体不同
多态
同一个方法可以根据发送对象的不同而采用多种不同的行为方式
一个对象的实际类型是确定的
new Student();
new Person();
但可以指向的引用类型就不确定了:父类的引用指向子类
//Student extends Person
Student s1 = new Student();
Person s2 = new Student();
Object s3 = =new Student(); //Object类是所有类的祖宗类
执行看左边,编译看右边
子类型能调用的方法都是自己的或是父类的
父类型可以指向子类型但不能调用子类型独有的方法
类型转换,子类重写了父类的方法调用子类的方法
(Student) s2).test();
注意点
- 多态是方法的多态,属性没有多态
- 类型转换异常
ClassCastException
- 前提条件:有继承关系,方法需要重写,父类引用指向子类对象
Father f1 = new Son()
- 补充:
static \ final \ private
修饰的方法不能重写
instanceof
X instanceof Y
测试 X
是否是 Y
(类) 的实例,返回 boolean 的数据类型。
如果 X
和 Y
之间存在父子关系就可以编译通过
总结
- 父类引用指向子类的对象
- 把子类转换为父类,向上转型,可能丢失自己本来的一些方法
- 把父类转换为子类,向下转型:强制转换
- 可以方便方法调用,减少重复代码
static
属性
package com.oop.demo06;
//static
public class Student {
private static int age; //静态变量
private double score; //非静态变量
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);
}
}
方法
package com.oop.demo06;
//static
public class Student {
public void run(){} //非静态方法
public static void go(){} //静态方法
public static void main(String[] args) {
go();
run(); //报错
Student.go();
Student.run(); //报错
new Student().run();
}
}
代码块
静态代码块最先执行且只执行一次
package com.oop.demo06;
public 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();
}
}
运行结果:
抽象类
- 抽象类不能new 只能考子类实现
- 抽象类中可以写普通方法
- 抽象方法只能在抽象类中
接口
接口的本质是契约
接口中无法写方法,主要起约束作用
代码实现
//实现多个接口
public class UserServiceImol implements UserService,TimeService{}
作用
- 约束
- 定义方法,让不同的人进行实现
- 接口中定义的变量都是常量
public static final
- 接口中的所有定义都是抽象的
public abstract
- 接口不能背实例化,且没有构造方法
implements
可以实现多个接口- 接口中的方法必须要重写
内部类
在一个类的内部再定义一个类
成员内部类
package com.oop.demo09;
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);
}
}
}
内部类可以直接获取外部类的私有属性和私有方法
一个java文件中只能有有个public class
,但可以有很多个class
文件
匿名内部类
package com.oop.demo09;
public class Test {
public static void main(String[] args) {
new Apple().eat();
UserService userService = new UserService() {
@Override
public void hello() {
}
};
}
}
class Apple{
public void eat(){
System.out.println("eatApple");
}
}
interface UserService{
void hello();
}