【Java学习之面向对象】

面向对象

什么是面向对象?

面向对象顾名思义就是把现实中的事务都抽象成为程序设计中的“对象”,其基本思想是一切皆对象,是一种“自下而上”的设计语言,先设计组件,再完成拼装

类:用来描述一个对象的基本范式模板,创建对象的时候参照这个模板来进行创建,即构造器

引用数据类型可以相当于是自己定义的一种全新的数据类型,是一种自定义的数据类型,类似于一个对象;

成员

成员是属于对象的,而不是属于类的,所以每个对象虽然是依照类来创建,但可以有不同的成员属性

局部变量是在代码块中的变量,就是局部位置。其他的位置都是成员位置,成员变量随着对象的消亡而消亡;

this

this关键字指向的是当前对象中的成员变量,用来和局部变量做区分

所有的成员方法都会隐含一个this传参,指向的就是当前的对象,但由于就近原则,如果方法的形参列表中有一个同名的局部变量,就会默认使用局部变量,因此需要用this来指向成员变量

这里要注意:static方法是没有隐含一个this传参的,如果要访问成员变量就需要创建对象

构造方法

构造方法必须和类名相同,new对象会自动调用构造方法,并且构造方法无法通过普通方法的调用方式来调用

构造方法可以重载

其他方法也可以和类名相同,但必须带有返回值或者void

构造方法的赋值永远是最后执行的,你可以永远相信构造器

static

静态属性是属于类的而不是对象的,是全体对象所共享的,包括变量和方法

静态成员的加载是随着类加载进行的,且不依赖对象而存在

类加载只有一次,所以静态成员也只有一份,且被所有对象共享

​ 这里注意与成员变量的区别:成员变量是每个对象独一份的

静态成员使用类名.的形式来访问,不建议通过对象名访问

静态变量存放在方法区中的静态区,被所有对象共享;

成员变量存放在堆内存中,每个对象独享自己的成员变量;

不存在静态的局部变量

匿名对象

没有引用指向,直接new出来的对象就是匿名对象

使用的场景:作为参数、返回值

使用一次之后就会被回收,无法再次访问到

代码块

局部代码块

基本用不着,就是用来限制局部变量的生命周期,优化内存

构造代码块

定义在类的成员位置,随着构造器的执行而执行,

显式赋值和构造代码块的执行顺序:谁写在上面就先执行谁

静态代码块

随着类加载的进行而执行,可以看作一个在类加载过程中会被自动调用的静态方法,不能在里面调用非静态的成员

和构造代码块一样,在对静态变量进行赋值的时候,谁写在上面就先执行谁

如果一个类的静态代码块没有被执行,就说明没有完全类加载

导包

这里要注意,在使用智能导入的时候会根据需要来智能导入需要的类

import + 包名.*;

但有一个条件:如果不导入对应包下的类就会报错,才会导入

访问权限修饰符

public:任意类都可访问,不限制访问权限

protected:同包下的其他类和其他包的子类可访问

deafault:默认权限,只有同包下的其他类能访问,不关心是不是子类

private:只有同类中的其他成员可见

面向对象的三大特征

封装

将设计者和使用者区分开来,使用者只用关心怎么使用,不必关心怎么实现

继承

Java中,一个子类只能有一个(直接)父类,

父类对象的范围大

子类继承了父类的成员,如果在父类中修改成员变量和方法,会影响所有子类

Java中没有多继承,祖先类都是objec

不能继承的:私有成员不能继承,构造方法不能继承

静态成员可以继承

子类对象的初始化

类加载是先父后子的,但成员变量都会有默认初始化具有默认值,这个过程不考虑先后的顺序。

子类对象在创建后,在自身的内存区中会有一部分用来存放父类的对象属性

除了默认初始化外的其他赋值方式都是先父后子的

隐式初始化:在子类的构造器中,如果没有this、super,会永远默认在第一行调用父类的无参构造,但无法完成父类成员变量的赋值,此时父类的成员变量只具有默认值

super关键字指向的是父类中的成员,受访问权限的限制,this关键字关键字指向的是自身对象,不受访问权限的限制

方法重写:子类中出现与父类同名的方法,会将父类的方法覆盖掉,但仍可以用super关键字来访问

要求:方法名相同,形参列表相同,必须是子类重写父类,不能抛出更多异常,访问权限只能更加宽松,返回值类型如果是引用数据类型,可以返回兼容的类型(子类)

不能重写的方法:私有、静态、构造方法

final

final修饰类表示无法继承

final修饰方法表示无法被重写,但可以被继承

final修饰变量:表示将该变量设置为常量

修饰基本数据类型表示值不可更改,修饰引用数据类型表示引用指向的地址值不可以更改,即该引用无法指向一个新的对象,但对象中的内容仍然是可以更改的

方法体中用final修饰局部变量表示该变量无法改变

方法的形参列表中用final修饰表示实参一旦传入,就无法修改了

成员常量:final 修饰的就是成员常量,无论使用什么方法,只能赋值一次并且不能更改,默认值不能作为常量,所以也必须要赋值,但每个对象都可以拥有属于自己的成员常量

全局常量:final修饰的静态变量,访问全局常量不会触发静态代码块

多态

多态发生的条件:父类引用指向子类对象,并有方法重写

成员变量的访问特征:编译时(访问范围)看左边,运行时(访问结果)看左边

成员方法的访问:编译(访问范围)看左边,运行时(调用结果)看右边

​ 这里注意:不管是什么方法,都只会看右边的结果,包括静态

向上转型:子类引用转父类引用,不会出问题

向下转型:父类引用强转子类引用,可能出问题

​ 要判断转向的那个子类引用和对应的那个对象是否是相同类型

引用名 instanceof 类名

抽象类

可以定义抽象方法,abstract,没有方法体,必须被子类重写,不能和final一起使用,但如果是抽象类继承抽象类,可以不用重写

抽象类可以有普通的成员方法和变量,也可以被继承

抽象类不能创建对象,但可以有构造器

除了多出一个抽象方法之外,别的都和普通类一样

任何不能被继承、重写的方法都不能定义为抽象

接口

访问权限只有public和默认

接口不受多继承限制,可以被多实现,抽象类继承接口可以不重写

如果一个类实现接口并继承别的类,要"先继承再实现"

接口的方法默认被public abstract修饰

接口的成员变量默认是全局常量,必须用显式赋值,接口中也没有静态代码块

接口中可以有默认方法default和静态方法static

接口和接口之间可以多继承,但接口和类不能相互继承

内部类

外围类:包含内部类的类

外部类:不相关的其他类

成员内部类

​ 不能有静态成员,即无法使用static

访问特点

​ 内部类与外围类:访问不受权限的限制,包括私有

内部类访问外围类成员:

成员内部类的方法中隐含有自身对象和外围类的对象,所以可以直接访问外围类的成员,但如果出现同名的情况,遵循就近原则,如果要访问外围类的成员,自身的对象用this指向,外围类对象用外围类类名.this"指向

外围类访问内部类成员:

​ 成员方法中:需要创建内部类对象,因为外围类自身的对象已经存在,直接new 内部类即可,如果有同名的情况,用对象名指向的就是内部类,否则就是外围类

​ 静态方法中:需要先创建外围类对象,再在此基础上创建内部类对象

MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz();

外部类访问内部类成员:

首先要有外围类的访问权限,其次还要有内部类的访问权限

先创建外围类对象,再创建内部类对象,接收的时候要写明该内部类属于哪个外围类

EnclosedClazz.MemberInnerClazz mic2 = new EnclosedClazz().new MemberInnerClazz();(

创建完之后,用对象名访问

成员内部类访问外部类:

​ 直接创建对象就能访问,受访问权限限制

静态内部类

静态内部类是一个独立的类,相当于嵌套在外围类中,和外围类没有强依赖关系

内部类和外围类之间不受访问权限的影响,但由于静态成员是不带有对象的,因此要访问谁,就创建谁的对象来访问

外部类访问静态内部类成员,之间创建静态内部类对象即可,但在使用引用接收的时候要表明该静态内部类属于哪个外围类

外围类类名.静态内部类类名

静态内部类访问外部类直接创建对象,受权限的限制

静态内部类的类加载和创建对象都和外围类没有直接的关系,不会互相触发

局部内部类

定义在一个方法或者作用域之中的类,没有访问权限修饰符,其他特点和成员内部类一致

局部内部类访问外围类成员:

1.在外围类的成员方法中定义的局部内部类:

访问特点与普通成员内部类一致

2.在静态方法中定义的局部内部类:

需要创建外围类对象才能访问外围类成员

外围类访问局部内部类成员:只能在装着局部内部类的方法中创建对象才能访问

外部类不能访问局部内部类成员,但局部内部类可以访问外部类成员

局部内部类的成员方法中不能修改方法的局部变量,是一个实际上的常量

lambda

匿名内部类

没有引用指向,相当于是一个类/接口的子类的类体,用来重写里面的方法

匿名内部类实质上就是创建一个子类对象,

匿名内部类语法中的小括号可以填入参数表示调用某个构造方法,但是注意只有类有构造器

使用场景:方法需要传入或者返回一个对象

lambda表达式

是特殊的匿名内部类

使用前提:只能实现功能接口,相当于该接口的子类

语法:()->{}

lambda表达式类型的推断:

1.直接用父类接口引用接收

2.告诉编译器类型:(父接口的名字)lambda表达式

3.借助方法的形参列表或者返回值

简化

形参列表:

形参的数据类型可以简化,如果只有一个形参,括号可以省略,但如果没有形参就不能省略

方法体:如果只有一条语句,可以省略大括号,如果是返回值语句,return也能省略

方法引用:

功能接口 接口名 = 方法的归属者::方法名;

静态方法的归属者是类,成员方法是对象

什么样的方法能被引用:返回值类型一直,形参列表中的数量、类型、位置必须对应,名字无所谓

lambda表达式只能重写方法,不能定义成员

你可能感兴趣的:(java,学习,jvm)