面向对象基础

什么是类?什么是对象?

现实生活中是由很多很多对象组成的,基于对象抽出了类

对象:软件中真实存在的单个个体/东西

类:类别/类型,代表一类个体

类是对象的模子,对象是类的具体的实例

类中可以包含:

对象的属性/特征-----------------------成员变量
对象的行为/动作-----------------------方法
一个类可以创建多个对象

如何创建类?如何创建对象?如何访问成员?

方法的重载(overload/overloading):---------------更加方便用户的访问

发生在同一类中,方法名相同,参数列表不同
编译器在编译时会根据方法的签名自动绑定方法

构造方法:构造函数、构造器、构建器---------复用给成员变量赋初值代码

作用:给成员变量赋初始值
与类同名,没有返回值类型(连void都没有)
在创建(new)对象时被自动调用
若自己不写构造方法,则编译器默认提供一个无参构造方法,若自己写了构造方法,则不再默认提供
构造方法可以重载
this:指代当前对象,哪个对象调用方法它指的就是哪个对象
​ 只能用在方法中,方法中访问成员变量之前默认有个this.
this的用法:

this.成员变量名-------------访问成员变量

成员变量与局部变量同名时,若想访问成员变量则this不能省略

this.方法名()

this()

null:表示空,没有指向任何对象
若引用的值为null,则该引用不能进行任何点操作了,
若操作则发生NullPointerException空指针异常


成员变量和局部变量是可以同名的:
----使用的时候默认采取就近原则
----若想访问成员变量,则this不能省略

内存管理:由JVM来管理的

堆:new出来的对象(包括成员变量)
栈:局部变量(包括方法的参数)
方法区:
成员变量:写在类中,方法外--------有默认值
局部变量:方法中------------------------没有默认值

数组也是一个对象,所以数组对象也存储在堆中,
将数组的元素当作成员变量一并存储在堆中
 

引用类型数组:

  • 与基本类型数组的区别:
  • 给数组元素赋值必须new一下
  • 若想访问对象数据必须通过数组元素打点

继承:

作用:代码复用
通过extends来实现继承
超类/父类:共有的属性和行为
派生类/子类:特有的属性和行为
派生类既能访问自己的,也能访问超类,但是超类不能访问派生类的
一个超类可以有多个派生类,一个派生类只能有一个超类---------单一继承
具有传递性
java规定:构造派生类之前必须先构造超类
在派生类的构造方法中若没有调用超类的构造方法,则默认super()调用超类的无参构造方法
在派生类的构造方法中若自己调用了超类的构造方法,则不再默认提供
super()调用超类构造方法,必须位于派生类构造方法的第1行

super:指代当前对象的超类对象
super的用法:

super.成员变量名
super.方法名()
super()

向上造型:
超类型的引用指向派生类的对象
能点出来什么,看引用的类型
方法的重写(override/overriding):重新写
发生在父子类中,方法名相同,参数列表相同
重写方法被调用时,看对象的类型
重写遵循"两同两小一大"原则:
两同:
方法名相同
参数列表相同
两小:
派生类方法的返回值类型小于或等于超类方法的
void和基本类型时,必须相等
引用类型时,小于或等于
派生类方法抛出的异常小于或等于超类方法的
一大:派生类方法的访问权限大于或等于超类方法的
重写与重载的区别:
重写(override):发生在父子类中,方法名相同,参数列表相同
重载(overload):发生在同一类中,方法名相同,参数列表不同
 

static final常量:
必须声明同时初始化
类名点来访问,不能被改变
建议:常量名所有字母都大写,多个单词用_分隔
编译器在编译时会将常量直接替换为具体的数,效率高
何时用:数据永远不变,并且经常使用
抽象方法:
由abstract修饰
只有方法的定义,没有具体的实现(连{}都没有)
抽象类:
由abstract修饰
包含抽象方法的类必须是抽象类
抽象类不能被实例化(new对象)
抽象类是需要被继承的,派生类:
重写所有抽象方法-----------------变不完整为完整
也声明为抽象类---------------------一般不这么用
抽象类的意义:
封装共有的属性和行为---------------代码复用
为所有派生类提供统一的类型------向上造型
可以包含抽象方法,为所有派生类提供统一的入口(能点出来),
派生类的行为不同,但入口是一致的,同时相当于定义了一个标准(强制重写)
补充:
设计规则:
将共有的属性和行为,抽到超类中-------------抽共性
若对象的行为都一样,设计为普通方法
若对象的行为不一样,设计为抽象方法


抽象方法/抽象类的疑问:
抽象方法存的意义是什么?
保证当发生向上造型时,通过超类的引用能点出来那个方法
既然意义只在于能点出来,那为什么不设计为普通方法呢?
若设计为普通方法,则派生类可以重写也可以不重写,而设计为抽象方法,可以强制派生类必须重写
       

 //3)大括号中的为派生类的类体
        Aoo o1 = new Aoo(){
        };

        //1)创建了Aoo的一个派生类,但是没有名字
        //2)为该派生类创建了一个对象,名为o2
        //3)大括号中的为派生类的类体
        Aoo o2 = new Aoo(){
        };

        int num = 5;
        num = 55;
        //1)创建了Boo的一个派生类,但是没有名字
        //2)为该派生类创建了一个对象,名为o3
        //3)大括号中的为派生类的类体
        Boo o3 = new Boo(){
            void show(){
                System.out.println("showshow");
                //在匿名内部类中会默认外面的变量为final的----API时会用
                //num = 55; //编译错误
            }
        };
        o3.show();

    }
}

abstract class Boo{
    abstract void show();
}

abstract class Aoo{
}


成员内部类:应用率低
类中套类,外面的称为外部类,里面的称为内部类
内部类通常只服务于外部类,对外不具备可见性
内部类对象通常在外部类中创建
内部类中可以直接访问外部类的成员(包括私有的)
内部类中有个隐式的引用指向了创建它的外部类对象:外部类名.this----API时会用
匿名内部类:-----------------------大大简化代码
若想创建一个类(派生类)的对象,并且对象只被创建一次,可以做成匿名内部类
在匿名内部类中默认外面的变量为final的----这是规定,记住就行了-----API时会用
面试题:问:内部类有独立的.class吗? 答:有

隐式的引用:
this:指代当前对象
super:指代当前对象的超类对象
外部类名.this:指代当前对象的外部类对象
做功能的套路:
先写行为/方法:
若为某对象所特有的行为,则将方法设计在特定的类中
若为所有对象所共有的行为,则将方法设计在超类中
窗口调用:

  1. 若为定时发生的,则在定时器中调用
  2. 若为事件触发的,则在侦听器中调用
  3. 接口:
    • 是一种引用数据类型
    • 由interface定义
    • 只能包含常量和抽象方法
    • 接口不能被实例化(new对象)
    • 接口是需要被实现/继承的,实现类/派生类:
      ----必须重写所有抽象方法
    • 一个类可以实现多个接口,用逗号分隔,若又继承又实现时,应先继承后实现
    • 接口可以继承接口

多态:
意义:

  •         同一类型的引用指向不同的对象时,有不同的实现--------所有抽象方法都是多态的
  •         ----行为的多态:cut()、getImage()、move()…
  •         同一个对象被造型为不同的类型时,有不同的功能--------所有对象都是多态的
  •         ----对象的多态:例如:我、你、水…

向上造型/自动类型转换:
超类型的引用指向派生类的对象
能点出来什么,看引用的类型
能造型成为的数据类型有:超类+所实现的接口
强制类型转换,成功的条件只有如下两种:
引用所指向的对象,就是该类型
引用所指向的对象,实现了该接口或继承了该类
强转时若不符合如上条件,则发生ClassCastException类型转换异常
建议在强转之前先通过instanceof判断引用的对象是否是该类型

内存管理:由JVM来管理的

堆:

  • 存储new出来的对象(包括实例变量)
  • 垃圾:没有任何引用所指向的对象
  • 垃圾回收器(GC)不定时到内存中清扫垃圾,回收过程是透明的(看不到的),
  • 不一定一发现垃圾就立刻回收,通过调用System.gc()可以建议JVM尽快调度GC回收

实例变量的生命周期:

  • ​ 创建(new)对象时存储在堆中,对象被回收时一并被回收
  • 内存泄漏:不再使用的对象没有被及时的回收,严重的泄漏会导致系统的崩溃
  • 建议:不再使用的对象应及时将引用设置为null

栈:

  • 存储正在调用的方法中的局部变量(包括方法的参数)
  • 调用方法时,会在栈中为该方法分配一块对应的栈帧,栈帧中存储局部变量(包括方法的参数),方法调用结束时,栈帧被自动清除,局部变量一并被清除

局部变量的生命周期:
​         调用方法时存储在栈中,方法调用结束时与栈帧一并被清除

方法区:

  • 存储.class字节码文件(包括静态变量、所有方法)
  • 方法只有一份,通过this来区分具体的访问对象
  • 面向对象三大特征:

封装:

  • 类:封装的是对象的属性和行为
  • 方法:封装的是具体的业务逻辑功能实现
  • 访问控制修饰符:封装的是具体的访问权限,以保护数据的安全

继承:

  • 作用:代码复用
  • 超类:所有派生类所共有的属性和行为
  • 接口:部分派生类所共有的属性和行为
  • 派生类:派生类所特有的属性和行为
  • 单一继承、多接口实现,具有传递性

多态:

  • 行为多态:所有抽象方法都是多态的(通过方法的重写实现的)
  • 对象多态:所有对象都是多态的(通过向上造型来实现)
  • 向上造型、强制类型转换、instanceof判断

String:字符串类型

  • java.lang.String使用final修饰,不能被继承
  • java中的String在内存中采用Unicode编码方式,任何一个字符占用两个字节的编码
  • 字符串底层封装的是一个字符数组
  • 字符串一旦创建,对象内容永远无法改变,但字符串引用可以重新赋值------不变对象

常量池:

  • java对字符串有一个优化措施:字符串常量池(堆中)
  • java推荐我们使用字面量/直接量的方式来创建字符串,并且会缓存所有以字面量形式创建的字符串对象到常量池中,当使用相同字面量再创建对象时将复用常量池中的对象以减少内存开销,从而避免内存中堆积大量内容相同的字符串对象
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java小高

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值