面向对象
面向对象和面向过程
面向过程:面向过程它强调的是一种功能行为,以函数为最小单位,考虑怎么做。
面向对象:将功能封装成一个对象,强调具备了功能的对象,考虑是由谁来做。
面向对象的三大特征:封装、继承、多态
类(Class)和对象(Object)
类: 类是对一类事物的描述,是一种抽象化的概念
对象: 对象是一个实际存在的事物的个体,也因此被称之为实例
类的成员
属性:对应类中的成员变量
行为:对应类中成员方法
//类
class Person{
//属性
String name;
int age;
//行为
public void sleep(){
System.out.println("人睡觉");
}
}
实例化上面的类:通过new 关键字来实现
//实例化
public class PersonDemo{
public static void main(String[] args){
Person person = new Person();
}
}
对象属性或者方法的调用 通过 对象.属性 或者 对象.方法
public class PersonDemo{
public static void main(String[] args){
Person person = new Person();
//调用属性
person.name;
//调用方法
person.sleep();
}
}
对象的内存解析
案例1
public class PersonDemo {
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "Tom";
p1.isMale = true;
Person p2 = new Person();
p2.name = "Lucy";
p2.isMale = true;
}
}
class Person{
String name;
int age;
boolean isMale;
public void sleep(){
System.out.println("人睡觉");
}
}
成员变量和局部变量
- 成员变量
成员变量是定义在类中的变量
成员变量是可以使用权限修饰符的 private、default、protected、public
对于成员变量是有默认的初始化值的
成员变量是加载到堆空间中
成员变量允许是static 静态的
例如:
class Person{
private String name;
String gender;
}
- 局部变量
声明在方法内部,方法型参、代码块内、构造器形参、构造器方法内部的变量
局部变量是不可以使用权限修饰符的
局部变量是没有默认初始化值的,所以我们一定要进行值的初始化
局部变量是加载到栈空间中的
局部变量中是不允许声明静态的变量
例如:
class Person(){
//方法型参
public void nation(String nation){
}
public void sleep(){
//方法内部
int seconed = 1000;
}
//代码块内部
{
int age = 0;
}
//构造器形式参数
public Person(String name){
}
//构造器内部参数
public Person(){
int age = 18;
}
}
方法的声明定义
定义格式1:
权限修饰符 返回值类型 方法名(){
// code
}
定义格式2:
权限修饰符 返回值类型 方法名(形参1,形参2 .... 形参N){
// code
}
定义格式3:
权限修饰符 返回值类型 方法名(形参1,形参2 .... 形参N){
// code
return value;
}
方法中可以调用方法,但是在方法中不能在定义方法
方法重载
方法重载的概念:在同一个类中,具有一个以上的同名方法,只要他们的参数个数和参数类型不同即可
重载的特点:与返回值的类型无关,只看参数列表,并且参数列表不同,参数的类型或者参数的个数不同即可
案例:
int add(int x,int y){
return x+y;
}
int add(int x,int y,int z){
return x+y+z;
}
double add(double x,double y){
return x+y;
}
方法参数的值传递机制
基本类型的值传递
引用类型的值传递
构造器
构造器的作用,就是用来创建对象
- 如果没有显示的定义类的构造器的化,则系统默认提供一个空参的构造器
- 构造器的名字和类名相同
- 不声明返回值累心那个
- 不能被static、final、synchronized、abstract、native修饰,不能有return返回值
- 一旦显示的定义了构造器以后,系统将不在提供默认的构造器
this 关键字
this可以调用类的属性,方法和构造器
如果形参和属性的值相同就必须要使用this.变量 的方式来表明当前的属性而非形参
-
在类的构造器中,可以显示的使用this(形参列表)的方式,调用本类中指定的其他构造器
-
构造器中不能通过this(形参列表)方式调用自己
-
如果一个类中有n个构造器,则最多有n-1个构造器使用了this(形参列表)
-
如果this(形参列表)必须声明在当前构造器的首行
封装与隐藏
封装:隐藏对象每部的复杂性,只是对外提供相应的接口,便于外界的调用,从而提高系统的可扩展性,和可维护性
封装性的体现:我们将类的属性进行私有化的同时,提供公共的get方法和set方法
例子
class Person{
private String name;
public String getName(){
return this.name;
}
public String setName(name){
this.name = name;
}
}
权限修饰符号
继承性
class 父类 extends 子类 {
// code
}
一旦 子类继承父类以后,子类会获取到父类中声明的所有属性和方法,特别的情况下,如果父类中声明为private的属性或者方法,子类继承父类以后,仍然认为获取到了父类中的属性或者方法,只是由于封装性的影响不可以直接调用。
子类也可以有自己的属性或者方法,对它的父类实行扩展
Java只支持单继承,不允许进行多重继承,一个子类就可以有一个父类,但是一个父类可以派生出多个子类
如果说我们没有显示的去指定继承的父类,默认则是继承Java.lang.Object类,
子父类的加载流程:父类的静态域-子类的静态域 父类的非静态域-父类的构造函数 子类的非静态域-子类的构造函数
public class SuperClassDemo {
public static void main(String[] args) {
new subClass();
}
}
class superClass{
{
System.out.println("superClass block");
}
static {
System.out.println("static superClass block");
}
public superClass(){
System.out.println("superClass Contructor method");
}
}
class subClass extends superClass{
{
System.out.println("subClass block");
}
static{
System.out.println("static subClass block");
}
public subClass(){
System.out.println("subClass Contructor method");
}
}
执行结果:
方法的重写
方法的重写的定义:在子类中可以根据需要对父类中继承的方法来进行修改,也称之为重写
方法重写的要求:
-
子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
-
子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型
-
子类重写的方法使用的访问权限不能小于父类被重写的方法的访问权限,子类不能重写父类中声明为private权限的方法
-
子类方法抛出的异常不能大于父类被重写方法的异常
super的使用
super可以理解为:父类的
super可以用来调用:属性、方法、构造器
Super的使用:
我们在可以在子类的方法或者构造器中。通过使用Super.属性 或者 Super.方法 的方式显示的调用父类中声明的属性或者方法。在通常的情况下,可以省略Super
特殊情况下,当子类和父类中定义了同名的属性时候,我们想要在子类中访问到父类中的属性,就需要显示的使用Super
特殊情况,当子类重写了父类中的方法,我们想要在子类方法中调用父类中被重写的方法同时,则必须要使用Super.方法
Super调用构造器:
-
可以在子类中显示的使用构造器 super(形参列表),调用父类中声明的指定的构造器
-
super(形参列表) 的使用,必须在子类构造器的首行
-
我们在类的构造器中,针对this(形参列表) 和 super(形参列表) 只能二选一。
-
如果在构造器中没有明确声明,默认的是调用super()
-
在类的构造器中,至少有一个类的构造器使用了super(形参列表),去调用父类中的构造器
多态性
多态性:父类的引用指向子类的对象,可以直接应用在抽象类和接口上
Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明 该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。简 称:编译时,看左边;运行时,看右边。
若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
多态情况下, “看左边” :看的是父类的引用(父类中不具备子类特有的方法) “看右边” :看的是子类的对象(实际运行的是子类重写父类的方法
equlse 和 == 之间的区别
==:运算符号
- == 运算符号使用在基本数据类型变量和引用数据变量中
- 如果是比较基本数据类型的变量,则是比较两个变量保存的数据是否相等(不一定类型要相同) 如果比较的是引用数据类型,则是比较连个对象的地址值是否相同,即两个引用是否指向同一个对象实体
equlse():方法
equlse方法只能适用于引用数据类型
object类中的equlse是使用 == 来判断两个对象是否相等的
static
static 静态的
可以用来修饰属性、方法、代码块、内部类
修饰属性
属性:属性又可以分为实例变量和静态变量
实例变量:在我们创建类的多个对象,每一个对象都独立拥有一套类中的非静态属性,当我们改变其中一个对象中的非静态属性时候,不会导致其他的对象中同样的属性值的修改
静态变量:我们创建类的多个对象,多个对象之江共享一个静态变量。当通过某一个对象修改静态变量的时候,会导致其他对象调用此静态变量时候,是修改过了的
静态变量是随着类的加载而加载,
静态变量的加载要早于对象的创建
由于类只会加载一次,则静态变量在内存中也只会存在一份
修饰方法
静态方法
权限修饰符 static 返回值类型 方法名(){
//code
}
静态方法的调用:可以通过 类名.静态方法名
静态方法中只可以调用静态的方法或者属性,非静态方法中可以调用非静态的方法或者属性,也可以调用静态的方法或者属性
静态方法内部不可以使用this、super关键字
代码块
静态代码块
static{
//code
}
-
内部中可以有输出的语句
-
随着类的加载而加载,而且只加载一次
-
作用:初始化类的信息
-
如果一个类中定义了多个代码块,则按照声明后的先后顺序先后执行
-
静态代码块的执行要有限与非静态代码块
-
静态的代码块只能调用静态的结构,例如静态方法,静态属性,不能调用非静态的结构
非静态代码块
{
//code
}
-
内部类中可以输出语句
-
随着对象的创建而执行
-
每次创建一个对象,就会执行一次非静态代码块
-
作用:可以在创建对象的时候,对属性初始化
-
如果一个类周昂定义了多个非静态的代码块,则按照声明的先后顺序进行执行
-
非静态代码块可以调用静态的属性、静态的的方法、或者非静态的属性、非静态的方法
final关键字
final 可以用来修饰类、方法、变量
-
被final修饰的类不可以被继承
-
被final修饰的方法不可以被重写
-
被final修饰的变量,就会变成一个常量
-
final修饰局部变量
修饰的位置是形参
//此时的形参 a 就是一个常量,不可以在被改变了 public void m(final int a){ //code }
抽象类(abstract)
abstract抽象的
abstract 可以用来修饰类、方法
抽象类定义格式
abstract class 类名{
//code
}
抽象方法定义格式:
权限修饰符 abstract 返回值类型 方法名();
抽象类不可以被实例化,抽象类中一定有构造器,便于子类的初始化调用
抽象方法没有方法体,只有方法的声明
包含抽象方法的类一定是一个抽象类
抽象类中不一定包含抽象方法
子类继承抽象类,重写了抽象类中的抽象方法,那么该子类可以被实例化
如果说子类继承抽象类,但是并没有重写抽象方法,那么该子类要定义成一个抽象方法
abstract不能用来修饰属性、构造器,不能修饰私有方法,不能修饰静态方法,不能修饰final方法
接口Interface
接口的定义
JDK1.7 及以前
只可以定义全局常量和抽象方法
全局常量 public static final
抽象方法 public abstract
JDK1.8及以后
除了定义全局常量和抽象方法,还可以定义静态方法,默认方法
接口他是不可以被实例化的,需要通过类的实现去实现接口中所有的抽象方法,然后去实现实例化
类是可以实现多个接口的
class 类名 implements 接口1,接口2{
// code
}
接口中的静态方法,只能通过接口来调用
通过实现类的对象,可以调用接口中默认的方法。如果重写了接口中的默认方法,调用的时候,仍然是重写以后的方法,如果子类没有重写父类的默认方法,默认调用的是父类中的同名同参数的方法
在子类中实现多个接口,而多个接口中有同名的参数方法,会产生接口冲突
内部类
内部类:在Java中允许一个类中定义另外一个类。称之为内部类(Inner class)
class A{
//内部类
class B{
}
}
内部类的分类:成员内部类 和 局部内部类
成员内部类可以定义属性、方法、构造器等
可以被final进行修饰,表示这个类不可以被继承
可以被abstract进行修饰
成员内部类的实例化
外部类.内部类 = new 外部类.内部类()
外部类 外部类名称 = new 外部类();
外部类.内部类 变量名 = 外部类名称.new 内部类();