1️⃣ 一、什么是面向对象
🚋 1、介绍
面向对象编程(Object-Oriented Programming,OOP),本质是:以类的方式组织代码,以对象的方式组织(封装)数据。具有三大特性:
封装
、继承
、多态
。
🎈 2、思考角度
- 从认知论角度考虑,先存在对象,再有类的存在;对象是具体的事物,类是对对象的抽象。
- 从代码运行角度考虑,是先存在类再有对象(new出来的),类是对象的模板。
补充:静态方法是和类一起加载的;
非静态方法需要在类实例化之后才存在。
2️⃣ 二、值传递与引用传递
🚋 1、值传递
public class Main {
public static void main(String[] args) {
int a = 5;
new Main().change(a);
System.out.println("a = " + a);//这里的值仍然是5
}
public void change(int a){
a = 10;
}
}
🎈 2、引用传递
public class Main {
public static void main(String[] args) {
Person person = new Person();
System.out.println(person.name);//原始名字
new Main().change(person);
System.out.println(person.name);//更改后的名字
}
public void change(Person person){
person.name = "李四";
}
}
class Person{
String name = "张三";
}
3️⃣ 三、类与对象
🚋 1、简介
类是一种抽象的数据类型,它是对某一类事物整体描述或定义,但是并不能代表某一个具体的事物,类中只有类的属性以及类的方法------------>模板;
对象是抽象概念的具体实例,需要通过new进行实例化--------------------->具体实现。
补充:使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中的构造器进行调用。
4️⃣ 四、构造器
🚋 1、简介
类中的构造器也成为构造方法,在进行创建对象的时候必须调用的;
特点:
-
类中的构造器必须和类的名字相同;
-
类中的构造器必须没有返回值,但也不能写 void;
====快捷键 :alt + insert ====
🎈 2、使用
在不显式声明有参构造器的时候,编译器会默认给类中添上无参构造器;
在使用new关键字时,本质是在调用构造器;
一旦定义了有参构造,无参构造器就必须显式定义;
构造器可以进行重载。
5️⃣ 五、封装
🚋 1、简介
程序设计追求"高内聚,低耦合"
- 高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;
- 低耦合就是仅暴露少量的方法给外部使用。
🎈 2、使用
封装就是进行数据隐藏,通常情况下,应该禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,也就是信息的隐藏。
通过使用 get / set 进行属性私有,get 获得这个数据,set 给这个数据置值 ---------->同样可以进行方法的重载
快捷键:alt + insert
🌈 3、好处
- 提高程序的安全性,保护数据
- 隐藏代码的实现细节
- 统一接口
- 增加系统的可维护性
6️⃣ 六、继承
🚋 1、简介
继承的本质是对某一批类的一种抽象,从而实现对现实世界更好的建模。
🎈 2、使用
使用 extends 关键字,扩展,子类(派生类)是父类(基类)的扩展 xxx is a xxx 的关系
- Java 中类只有单继承,没有多继承(需要通过接口实现)
- 子类继承父类所有的方法和公有的属性
- 快捷键:ctrl + H 打开 继承树
- 在Java中所有的类都直接或间接继承于 Object 类
🌈 3、this、super 关键字
-
this 调用子类本身的属性或方法
-
super 调用父类的属性或方法
this 关键字 和 super 关键字必须只能出现一个,不能同时调用构造方法;
在子类的构造器中默认调用了父类的无参构造;
如果需要显式进行调用,则必须要在子类构造器的第一行;
this 关键字在没有继承关系的时候也可以使用;
super 关键字只能在继承条件下才可以使用。
📌 4、方法重写
方法的重写与属性无关,子类重写父类的方法
- 方法名必须相同
- 参数列表必须相同
- 修饰符:范围可以扩大 private ------> protected ---------> default ----------> public
- 抛出的异常:范围只能缩小,不能扩大 Exception(大) ------> ClassNotFoundException(小)
为什么需要进行重写?
父类的功能子类不一定需要,或者不一定满足
快捷键:alt + insert @Override
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
student1.test();//方法被重写了
Person student2 = new Student();
student2.test();//方法被重写了
Person student3 = new Person();
student3.test();//方法还没被重写
}
static class Person {
public void test() {
System.out.println("方法还没被重写!");
}
}
static class Student extends Person {
@Override
public void test() {
System.out.println("方法被重写了!");
}
}
}
补充:
若父类中的 test()和子类中的 test()方法均改为静态的
结果需要看 new 的左边,对象能够执行哪些方法,主要看对象的左边的类型。
public class Main {
public static void main(String[] args) {
Student student1 = new Student();
student1.test();//方法被重写了
Person student2 = new Student();
student2.test();//方法还没被重写
Person student3 = new Person();
student3.test();//方法还没被重写
}
static class Person {
public static void test() {
System.out.println("方法还没被重写!");
}
}
static class Student extends Person {
public static void test() {
System.out.println("方法被重写了!");
}
}
}
7️⃣ 七、多态
🚋 1、简介
动态编译:类型
多态是方法的多态,属性没有多态。
同一个方法可以根据发送对象的不同而采用多种不同的行为方式;
一个对象的实际类型是确定的,但是可以指向对象的引用的类型可以有很多
🎈 2、使用
父类的引用能够指向子类对象
public class Main {
public static void main(String[] args) {
Student student = new Student();
Person student1 = new Student();
Object student2 = new Student();
}
static class Person {
}
static class Student extends Person {
}
}
🌈 3、注意
- 多态是方法的多态,属性没有多态;
- 父类与子类之间需要有一定的联系,才能够进行类型转换,否则会存在类型转换异常(ClassCastException);
- 存在条件:在继承关系中有方法的重写,有两个相同的方法名,计算机不清楚调用哪一个方法;
- 父类引用指向子类对象
- 哪些方法不能被重写
- 被static 修饰的静态方法,与类有关,和类同时存在,不属于实例
- 被 final 修饰的,在常量池中存在
- 被private 修饰的,是私有的方法,没有访问权限
📌4、instanceof 关键字
作用:进行类型转换,判断对象与已经存在的类型之间是否直接或者间接存在父子关系
先看要比较对象的引用,用联系的话继续运行,否则编译报错;再看声明右边的具体类型,有联系返回 true,否则返回 false
public class Main {
public static void main(String[] args) {
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Student student = new Student();
System.out.println(student instanceof Student);//true
System.out.println(student instanceof Teacher);//报错,没有联系
System.out.println(student instanceof Person);//true
System.out.println(student instanceof Object);//true
System.out.println(student instanceof String);//报错,没有联系
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Person person = new Student();
System.out.println(person instanceof Student);//true
System.out.println(person instanceof Teacher);//false
System.out.println(person instanceof Person);//true
System.out.println(person instanceof Object);//true
System.out.println(person instanceof String);//报错,没有联系
//Object > String
//Object > Person > Teacher
//Object > Person > Student
Object object = new Student();
System.out.println(object instanceof Student);//true
System.out.println(object instanceof Teacher);//false
System.out.println(object instanceof Person);//true
System.out.println(object instanceof Object);//true
System.out.println(object instanceof String);//false
}
static class Person {
}
static class Student extends Person {
}
static class Teacher extends Person {
}
}
⚽5、类型转换
多态就是自动类型转换,子类转为父类,向上转型
强制类型转换,父类转为子类,向下转型,存在丢失精度和方法
格式:(子类类型) 父类对象
public class Main {
public static void main(String[] args) {
Person person = new Student();//自动类型转换
Student student = (Student) person;//强制类型转换
Student student1 = new Student();
Person person1 = student1;//自动类型转换
}
static class Person {
}
static class Student extends Person {
}
static class Teacher extends Person {
}
}
注意
- 子类转换为父类,会丢失一些特有的方法
- 父类引用指向子类对象
- 多态的存在方便方法的调用,减少重复的代码
8️⃣八、static 关键字
🚋 1、属性
public class Main {
private static int age;//静态变量
private double score;//非静态变量
public static void main(String[] args) {
Main main = new Main();
//静态变量的调用方式
System.out.println(age);//直接调用
System.out.println(main.age);//通过对象调用
System.out.println(Main.age);//通过类名调用
//非静态变量的调用方式
/*System.out.println(score);*/ //报错,不能直接调用
System.out.println(main.score);//通过对象调用
/*System.out.println(Main.score);*/ //报错。不能通过类名调用
}
}
🎈 2、方法
public class Main {
public static void main(String[] args) {
Main main = new Main();
//非静态方法的调用方式
/*A();*/ //报错,不能直接调用
main.A();//可以通过对象调用
/*Main.A();*/ //报错,不能通过类名调用
//静态方法的调用方式
B();//可以直接调用
main.B();//可以通过对象调用
Main.B();//可以通过类名调用
}
//非静态方法
public void A() {
B(); //非静态方法可以调用静态方法和非静态方法
A();
}
//静态方法
public static void B() {
B(); //静态方法可以调用静态方法
/* A(); */ //报错,静态方法不能调用非静态方法
}
}
🌈 3、代码块
public class Main {
{
//匿名代码块 顺序在构造器之前 作用:赋初值
System.out.println("匿名代码块");// ---------------2
}
static{
//静态代码块 顺序与类加载相同 只执行一次
System.out.println("static 静态代码块"); // --------------1
}
public Main() {
System.out.println("构造方法");// --------------3
}
public static void main(String[] args) {
Main main = new Main();
System.out.println("================================");
Main main1 = new Main();//这一次不会打印 static 静态代码块
}
}
9️⃣ 九、抽象类
🚋 1、简介
abstract 修饰方法 为抽象方法
修饰类 为抽象类
抽象类中可以没有抽象方法,但是存在抽象方法的类一定要声明为抽象类
注意
- 抽象类不能够通过new关键字来创建对象,只能够让子类去继承它
- 抽象方法只有方法的声明,没有方法的实现,要通过子类来实现
- 子类如果要继承某个抽象类,那么就必须实现抽象类中没有实现的抽象方法,否则这个子类也要声明为抽象类
🎈 2、代码演示
public class Main {
public static void main(String[] args) {
/* new action(); */ //抽象类,不能够被实例化
new A();
}
}
class A extends action{
@Override //重写抽象类
public void doSomething1() {
//方法体
}
}
abstract class action{
//抽象类中可以有普通方法
public void doSomething(){
//方法体
}
public abstract void doSomething1();//抽象方法
}
🔟十、接口
🚋 1、区别
方法体内容 | |
---|---|
普通类 | 只有具体实现 |
抽象类 | 具体实现和规范(即抽象方法)都有 |
接口 | 只有规范 |
接口就是规范,定义的是一组规则。
接口是对对象的抽象的具体体现,是面向对象编程的核心
声明类的关键字是 class ,声明接口的关键字是 interface,并通过implements实现
实现了接口的类,就需要重写接口中的方法
利用接口可以实现多继承
重写方法的快捷键:alt + insert
🎈 2、代码演示
public class Main {
public static void main(String[] args) {
new A();
}
}
class A implements UserService,Timer{
@Override
public void run() {
}
@Override
public void eat() {
}
@Override
public void timer() {
}
}
interface Timer{
void timer();
}
interface UserService{
int AGR = 99;//属性 默认的修饰符为 public static final ——————为常量
public static final int SCORE = 100;
public abstract void run();
void eat();//方法 默认的修饰符为 public abstract
}
🌈 3、接口的作用
- 模板作用,对代码进行约束
- 定义一些方法,让不同的人实现
- 接口不能被实例化,而且接口中没有构造方法,抽象类中有构造方法
- implements可以实现多个接口
- 必须要重写接口中的方法
1️⃣1️⃣十一、内部类
内部类就是在一个类的内部再定义一个类
一个Java类中可以有多个class类,但是只能有一个public class
🚋 1、成员内部类
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();//实例外部类
Outer.Inner inner = outer.new Inner(); //通过这个外部类来实例化内部类
inner.in();
inner.getId();
inner.getOut();
}
}
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);
}
public void getOut(){ //获得外部类的方法
out();
}
}
}
🎈 2、静态内部类
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();//实例外部类
outer.out();
Outer.Inner inner = new Outer.Inner();
inner.in();
}
}
class Outer {
private int id = 10;
public void out() {
System.out.println("这是外部类的方法");
}
//这个内部类加上了static关键字--------------静态内部类
/*
静态内部类不能够访问非静态的属性,时间片不同
*/
public static class Inner {
public void in() {
System.out.println("这是内部类的方法");
}
public void getID(){
//静态内部类不能够访问非静态的属性或方法,时间片不同
/*System.out.println(id);*/
}
public void getOut(){
/*out();*/
}
}
}
🌈 3、局部内部类
public class Outer {
public static void main(String[] args) {
Outer outer = new Outer();
outer.method();
}
/*
方法中写内部类----------局部内部类(类似局部变量)
*/
public void method(){
class Inner{ // Inner类在method方法下
public void in(){ //内部类里面还可以再写方法
}
}
}
}
📌 4、匿名内部类
public class Main {
public static void main(String[] args) {
//常规写法
Test test = new Test(); //名字为 test
//匿名写法
new Test().eat(); //没有名字初始化类,不用实例保存到变量中
new UserService(){
@Override
public void run() {
System.out.println("run");//打印不出来
}
};
}
}
class Test{
public void eat(){
System.out.println("eat");
}
}
interface UserService{
void run();
}
说在最后📝:
✍创作不易,如果觉得文章写得还可以的话,就不要吝啬你的 👍 啦~ ✍