什么是面向对象
面向过程:
- 可以是看做步骤化的过程。分析出实现需求所需要的每一步,再通过函数逐步实现该步骤,依次调用函数即可
- 好比与把大象装进冰箱里分三步,第一步开冰箱门,第二步把大象放进去,第三步关上冰箱门
面向对象:
- Java语言是一门完全面向对象的编程语言
- 面向对象就是把需求按照功能等划分出来,把存在共性的部分封装成对象
- 创建了对象不是为了完成某一个步骤,而是描述某个事物在解决问题的步骤中的行为
类与对象
类: 是一组相关的属性和行为的集合(抽象的)
对象: 是类事物的具体表现形式(现实具体存在的个体)
成员变量: 事物的属性
成员方法: 事物的行为
以人为例,人类的姓名、性别、年龄等属性可被称为成员变量,人类能够交流、能够使用工具等行为可被称为成员方法
成员变量与局部变量的区别:
-
在类中的位置不同
成员变量:类中、方法外
局部变量:方法定义中、方法声明上 -
在内存中的位置不同
成员变量:在堆中
局部变量:在栈中 -
生命周期不同
成员变量:随对象的创建而存在,随对象的消失而消失
局部变量:随方法的调用而存在,随方法的调用完毕而消失 -
初始化不同
成员变量:有默认值
局部变量:需定义再赋值才可使用
构造方法
构造方法与其所在类的名字相同,但构造方法没有返回值
- 若在程序中未给出构造方法,则系统会自动提供一个无参构造方法
- 若在程序中给出了构造方法,则系统将不再提供默认的无参构造方法
- 若在程序中定义了有参构造方法,则必须再添加无参构造方法
- get、set方法则是起到封装的效果,不让用户直接操作成员
- 单例模式,可见博客https://blog.csdn.net/absolute_chen/article/details/93380566
new 对象
栈存放引用类型
堆存放具体的对象
封装
封装是指隐藏对象的属性和实现细节,仅对外提供公共访问方式
好处:
- 提高了代码的复用性
- 提高了安全性
封装原则:
- 将不需要对外提供的内容都隐藏起来
- 把属性隐藏,提供公共方法对其访问
- Private:私有的,可以修饰成员变量和成员方法。被private修饰的成员只能在本类中访问,所以外界想要操作类中的成员变量就必须通过调用类中的方法来实现
继承
Object类:
- Object类是java默认的提供的一个类,Object类是所有类的父类,也就是说任何一个类的定义的时候如果没有明确的继承一个父类的话,那么它就是Object的子类
- Object 类属于java.lang包,此包下的所有类在使用时无需手动导入,系统会在程序编译期间自动导入
- 常用方法:toString( )、equals()
extends:
- 继承就是子类继承父类的特征和和行为,使得子类对象(实例)具有父类的实例域和方法,还可以以此基础添加新方法和域来满足需求
- 继承需要符合的关系是:is-a,父类更通用,子类更具体
- java不支持多继承,即一个子类只能拥有一个父类
- java中,所有继承都是公有继承,子类拥有父类非private属性和方法
super、this关键字:
- this
引用隐式参数
调用该类的其他构造器 - super
调用父类的方法
调用父类的构造器
通过super关键字来实现对父类成员的访问,用来引用当前对象的父类,super与this引用不是类似的概念,因为super不是一个对象引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字,super指向父类,this是指向自己的引用
方法重写:
方法的重写是当程序中父类的某一个方法并不能满足子类的需求时,子类可以重新定义该方法的内容与功能来满足子类的需求的一种操作
- 重写的方法必须要和父类一模一样(包括返回值类型,方法名,参数列表)
- 重写的方法可以使用@Override注解来标识
- 子类中重写的方法的访问权限不能低于父类中方法的访问权限
- 权限修饰符 : private < 默认(什么都不写) < protected < public
多态
多态是同一个行为具有多个不同表现形式或形态的能力 or 多态就是同一个接口,使用不同的实例而执行不同操作
不够形象,ok->你家有亲属结婚了,让你们家派个人来参加婚礼,邀请函写的是让你爸来,但是实际上你去了,或者你妹妹去了,这都是可以的,因为你们代表的是你爸,但是在你们去之前他们也不知道谁会去,只知道是你们家的人。可能是你爸爸,可能是你们家的其他人代表你爸参加。这就是多态。
多态存在的三个必要条件:
- 继承
- 重写
- 基类引用指向派生类对象(引用还是指向基类) (Parent p = new Child(); )
多态又分为 编译时多态和运行时多态:
- 编译时多态:比如重载(Overload)
重载的意义是同一个类里,两个方法的名称相同,但参数列表不同 - 运行时多态:比如重写(Override)
参数必须要一样,且返回类型必须兼容。重写是派生类对基类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
附上一张网图
修饰符
类修饰符:
-
访问修饰符:
public: 代表主类,一个类中不能含有两个或以上的public修饰的类。其他外部类无访问控制修饰符,具有包访问性。 -
非访问修饰符:
abstract: 代表抽象类,子类继承后要重写abstract方法,如果不进行重写则默认子类依旧是抽象类
final: 代表终类,不能被其他类继承。被定义为 final 的类通常是一些有固定作用、用来完成某种标准功能的类。
类缺省访问控制符: 如果一个类没有访问控制符,说明它具有缺省的访问控制符特性。此时,这个类只能被同一个包中的类访问或引用。这一访问特性又称为包访问性
方法修饰符:
- 访问控制修饰符:
公共访问控制符public
保护访问控制符protected
缺省默认default
私有访问控制符private - 非访问控制修饰符:
抽象方法控制符abstract: abstract 修饰的方法称为抽象方法。抽象方法仅有方法头,没有方法体和具体实现。
静态方法控制符static: 用修饰符 static 修饰的方法称为静态方法。静态方法是属于整个类的类方法;而不使用static 修饰、限定的方法是属于某个具体类对象的方法。 由于 static方法是属于整个类的,所以它不能操纵和处理属于某个对象的成员变量,而只能处理属于整个类的成员变量,即 static 方法只能处理 static的域
最终方法控制符final: 用修饰符 final修饰的方法称为最终方法。最终方法是功能和内部语句不能更改的方法,即最终方法不能重写覆盖。final固定了方法所具有的功能和操作,防止当前类的子类对父类关键方法的错误定义,保证了程序的安全性和正确性。所有被 private 修饰符限定为私有的方法,以及所有包含在 final 类 ( 最终类) 中的方法,都被认为是最终方法
本地方法控制符native: 用修饰符 native 修饰的方法称为本地方法。为了提高程序的运行速度,需要用其它的高级语言书写程序的方法体,那么该方法可定义为本地方法用修饰符 native 来修饰
同步方法控制符synchronized: 该修饰符主要用于多线程程序中的协调和同步。
接口
为了声明一个接口,我们使用interface这个关键字,在接口中的所有方法都必须只声明方法标识,而不要去声明具体的方法体,因为具体的方法体的实现是由继承该接口的类来去实现的,因此,接口并不用管具体的实现。
接口中的属性默认为Public Static Final
一个类实现这个接口必须实现这个接口中定义的所有的抽象方法
只有一个方法的接口叫做函数式接口,可以使用lambda表达式简化
接口比抽象类更抽象
一个类可实现多个接口
可参考博客园:https://www.cnblogs.com/lqhhome/p/10746615.html (以动物为例讲解)
内部类
将一个类定义在另一个给类里面或者方法里面,这样的类就被称为内部类。
内部类可分为:
- 成员内部类
- 局部内部类
- 匿名内部类
- 静态内部类
成员内部类
简单定义如下
class A{
class B{
}
}
因为类A相对与类B在外面,我们且称类A为外部类。
成员内部类可以无条件访问外部类的属性和方法,但是外部类想要访问内部类属性或方法时,必须要创建一个内部类对象,然后通过该对象访问内部类的属性或方法
- 成员内部类无条件访问外部类的属性和方法
class A{
private String name = "外部类";
public void run(){
System.out.println("外部类运行");
}
class B{
public void say(){
System.out.println(name);
run();
}
}
}
- 外部类访问内部类属性和方法
class A{
private String name = "外部类";
public void run(){
System.out.println("外部类运行");
}
/*使用内部类的属性和方法*/
public void rerun(){
B b = new B();
System.out.println(b.value);
b.work();
}
class B{
private String value = "BBB";
public void work(){
System.out.println(name);
run();
}
}
}
- 外部类属性或方法隐藏
如果成员内部类的属性或者方法与外部类的同名,将导致外部类的这些属性与方法在内部类被隐藏,也可按照该格式调用,外部类.this.属性/方法。
class A{
private String name = "外部类";
public void run(){
System.out.println("外部类运行");
}
/*使用内部类的属性和方法*/
public void rerun(){
B b = new B();
System.out.println(b.value);
b.work();
}
class B{
private String value = "BBB";
private String name = "内部类";
public void work(){
System.out.println(C.this.name);
System.out.println(name);
run();
}
}
}
成员内部类的访问权限:
- private:仅外部类可访问
- protected:同包下或继承类可访问
- default:同包下可访问
- public:所有类可访问
局部内部类
局部内部类存在于方法中。
它和成员内部类的区别在于局部内部类的访问权限仅限于方法或作用域内。
注意事项: 局部内部类就像局部变量一样,前面不能访问修饰符以及static修饰符。
class C{
public void run(){
class D{
}
}
}
匿名内部类
匿名内部类也就是没有名字的内部类
正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写
但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口
abstract class Person {
public abstract void eat();
}
public class Demo {
public static void main(String[] args) {
Person p = new Person() {
public void eat() {
System.out.println("Eat! ");
}
};
p.eat();
}
}
静态内部类
静态内部类和成员内部类相比多了一个static修饰符。
它与类的静态成员变量一样是不依赖于外部类的。
因为外部类加载时只会加载静态域,所以静态内部类不能使用外部类的非静态变量与方法。
成员内部类里面是不能含静态属性或方法的。
class A {
static class B {
}
}
内部类的好处:
- 完善了Java多继承机制,由于每一个内部类都可以独立的继承接口或类,所以无论外部类是否继承或实现了某个类或接口,对于内部类没有影响
- 方便写事件驱动程序