java面向对象

java面向对象

  • 面向对象思想
    • 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程的思索。
    • 面向对象适合处理复杂的问题,适合处理需要多人协作的问题。
  • 对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思维去处理。

面向过程

  • 步骤清晰简单,第一步做什么,第二步做什么…
  • 面对过程适合处理一些较为简单的问题

面向对象

  • 面向对象编程(Object-Oriented Programming, OOP)
  • 面向对象编程的本质就是:以类的方式组织代码,以对象的组织(封装)数据。
  • 核心:抽象
  • 三大特性:
    • 封装
    • 继承
    • 多态
  • 从认识论角度考虑是先有对象后有类。对象,是具体的事物。类,是抽象的,是对对象的抽象。
  • 从代码运行角度考虑是先有类后有对象。类是对象的模板。

组成

变量

  • 类变量

在类里,整个类里可以使用,前面必须加static;“static int a = 666;”

  • 实例变量

在类里,从属于对象;“int age;//0”

如果不自行初始化,这个类型的默认值 0,0.0

布尔值:默认是false;除了基本类型,其他的默认值都是null;

  • 局部变量

在方法中,使用时必须声明和初始化值;“int cba = 666;"

在代码块中等

方法

概述

方法:用来完成特定功能的代码片段

包含:方法头和方法体

  • 结构 修饰符 返回值类型 方法名(参数类型 参数名){

​ 方法体

​ return 返回值;

​ }

分类
  • 类方法

用static修饰的方法。

由于类方法是属于整个类的,并不属于类的哪儿个对象,所以类方法的方法体中不能有与类的对象有关的内容。即类方法体有如下限制:

1.类方法中不能引用对象变量;

2.类方法中不能调用类的对象方法;

3.在类方法中不能调使用super,this关键字;

4.类方法不能被覆盖。

  • 实例方法

当一个类创建了一个对象后,这个对象就可以调用该类的方法(对象方法)。

1.实例方法中可以引用对象变量,也可以引用类变量;

2.实例方法中可以调用类方法;

3.对象方法中可以使用super,this关键字。

  • 理解

    当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址,当该类创建对象后,类中的实例方法才分配入口地址,从而实例方法可以被类创建的任何对象调用执行。需要注意的是,当我们创建第一个对象时,类中的实例方法就分配了入口地址,当再创建对象时,不再分配入口地址,也就是说,方法的入口地址被所有的对象共享,当所有的对象都不存在时,方法的入口地址才被取消。

    对于类中的类方法,在该类被加载到内存时,就分配了相应的入口地址。从而类方法不仅可以被类创建的任何对象调用执行,也可以直接通过类名调用。类方法的入口地址直到程序退出时才被取消。

    类方法在类的字节码加载到内存时就分配了入口地址。因此,Java语言允许通过类名直接调用类方法,而实例方法不能通过类名调用。在Java语言中,类中的类方法不可以操作实例变量,也不可以调用实例方法,这是因为在类创建对象之前,实例成员变量还没有分配内存,而且实例方法也没有入口地址。

调用

实例化这个类 new+类名+.方法名

因为static静态方法是和类一起加载,在创建的时候就已经有了 ,所以间接调用

重载

重载,相同的参数名 不同的形参

规则:

1.方法名称必须相同

2.参数列表必须不同(个数不同,或类型不同、参数排列顺序不同等)

3.方法返回值类型可以相同也可以不同

4.仅仅返回值不同不足以成为方法的重载

理论:方法名称相同时,编译器会根据调用方法的参数个数,参数类型等去逐个匹配,以选择对应的方法,匹配失败,则编译器报错

形参和实参
值传递和引用传递

java 是值传递:对象,本质还是值传递*

main

main()函数传递

可变参数

不定项参数

在方法声明中 指定参数类型后加一个省略号(…)

一个方法声明中只能指定一个可变参数,它必须是最后一个参数,任何普通参数必须在他之前声明

递归

递归:自己调用自己

递归结构包含两部分:

递归头:什么时候不调用自身方法。如果没有头,将陷入死循环

递归体:什么时候需要调用自身方法

最好不要使用递归(大计算不要使用)

构造器

类中的构造器也称为构造方法,是在进行创建对象的时候必须要调用的

作用

一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法。

特点

函数名与类名相同

不用定义返回值类型。(不同于void类型返回值,void是没有具体返回值类型;构造函数是连类型都没有)

不可以写return语句。(返回值类型都没有,也就不需要return语句了

注:一般函数不能调用构造函数,只有构造函数才能调用构造函数

理解

默认构造器如果没有定义构造器,则会默认一个无参构造器,这就是为什么你定义了一个对象,比如 People,没有定义任何构造器却可以new这个对象,比如 new People() 。如果自定义了构造器,则会覆盖默认构造器。

如何禁止对象被外部创建一些特殊需求,不希望定义的对象被外部创建(典型的就是单例了),那直接将构造器的修饰符改为 private 即可。这样就不能在外部通过new来创建这个对象了。

构造器重载与普通方法一样,构造器也支持重载。一个对象中是可以支持同时定义多个构造器,通过不同的参数列表来实现重载。经常看到代码中new一个对象时,有时传入参数,有时又可以不用传。比如:new People()跟new People(“张三”),这里就是重载了。

构造器的继承子类构造器会默认调用父类无参构造器,如果父类没有无参构造器,则必须在子类构造器的第一行通过 super关键字指定调用父类的哪个构造器。final类是不允许被继承的,编译器会报错。很好理解,由于final修饰符指的是不允许被修改,而继承中,子类是可以修改父类的,这里就产生冲突了,所以final类是不允许被继承的。

构造器、静态代码块、构造代码块的执行顺序,静态代码块:只在程序启动后执行一次,优先级最高构造代码块:任何一个构造器被调用的时候,都会先执行构造代码块,优先级低于静态代码块构造器:优先级低于构造代码块总结一下优先级:静态代码块 > 构造代码块 > 构造器

代码块

概述

用{}括起来的称为代码块

分类
  • 普通代码块:类中方法的方法体
  • 构造代码块:类中**{}**直接括起来的语句,每次创建对象都会被调用先于构造函数执行
  • 静态代码块:类中**static{}**括起来的语句,只执行一次先于构造代码块块执行
  • 同步代码块:类中synchronized(){}括起来的语句,多线程环境下互斥执行

内部类

内部类就是在一个类的内部在定义一个类

内部类的优缺点

内部类的优点:

  1. 内部类与外部类可以方便的访问彼此的私有域(包括私有方法、私有属性)。
  2. 内部类是另外一种封装,对外部的其他类隐藏。
  3. 内部类可以实现java的单继承局限。

内部类的缺点:

结构复杂。

创建内部类
创建非静态内部类

外部类.内部类 内部类对象 = new 外部类().new 内部类();

创建静态内部类

外部类.内部类 内部类对象 = new 外部类.内部类();

内部类的分类

在Java中内部类主要分为 成员内部类、静态内部类、方法内部类、匿名内部类

成员内部类

成员内部类是依附外部类的,只有创建了外部类才能创建内部类。

静态内部类

静态内部类的创建不需要依赖外部类可以直接创建。

静态内部类不可以使用任何外部类的非static类(包括属性和方法),但可以存在自己的成员变量。

方法内部类

方法内部类不允许使用访问权限修饰符(public、private、protected)均不允许。

方法内部类对外部完全隐藏,除了创建这个类的方法可以访问它以外,其他地方均不能访问 (换句话说其他方法或者类都不知道有这个类的存在)方法内部类对外部完全隐藏,出了创建这个类的方法可以访问它,其他地方均不能访问。
方法内部类如果想要使用方法形参,该形参必须使用final声明(JDK8形参变为隐式final声明)

匿名内部类

匿名内部类就是一个没有名字的方法内部类,因此特点和方法与方法内部类完全一致,除此之外,还有自己的特点:
1.匿名内部类必须继承一个抽象类或者实现一个接口。
2.匿名内部类没有类名,因此没有构造方法。

对象

所谓内部类就是在一个类内部进行其他类结构的嵌套操作。

类与对象的关系

  • 类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但是并不能代表某一个具体的事物。
    • 动物、植物、手机、电脑…
    • Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
  • 对象是抽象概念的具体实例
    • 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例。
    • 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念。

创建与初始化对象

使用new关键字创建的时候,除了分配内存空间之外,还会给创建好的对象进行默认的初始化以及对类中构造器的调用

三大特性

封装

  • 理解

    • 该露的露,该藏得藏
      • 我们程序设计要追求 “高内聚,低耦合”。高内聚就是将类的内部数据操作细节自己完成,不允许外部干涉;
      • 低耦合:尽量暴露少量的方法给外部使用。
    • 封装(数据的隐藏)
      • 通常,应禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问,这称为信息隐藏。
    • 属性私有,private ; get / set ;

继承

在 Java 中,所有的类,都默认、直接或者间接继承object

  • 继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
  • extends 的意思是“扩展”。子类是父类的扩展。
  • Java 中类只有单继承,没有多继承!
  • 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。
  • 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends 来表示。
  • 子类和父类之间,从意义上讲应该具有“is a”的关系。
特点
  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)
this

this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。

特点

普通的直接引用 this相当于是指向当前对象本身。

形参与成员名字重名,用this来区分

引用本类的构造函数

super

super可以理解为是指向自己超(父)类对象的一个指针,而这个超类指的是离自己最近的一个父类。

特点

普通的直接引用 与this类似,super相当于是指向当前对象的父类的引用,这样就可以用super.xxx来引用父类的成员。

子类中的成员变量或方法与父类中的成员变量或方法同名时,用super进行区分

引用父类构造函数

this vs super
  • super: 它引用当前对象的直接父类中的成员(用来访问直接父类中被隐藏的父类中成员数据或函数,基类与派生类中有相同成员定义时如:super.变量名 super.成员函数据名(实参)
  • this:它代表当前对象名(在程序中易产生二义性之处,应使用this来指明当前对象;如果函数的形参与类中的成员数据同名,这时需用this来指明成员变量名)
  • super()和this()类似,区别是,super()在子类中调用父类的构造方法,this()在本类内调用本类的其它构造方法。
  • super()和this()均需放在构造方法内第一行。
  • 尽管可以用this调用一个构造器,但却不能调用两个。
  • this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
  • this()和super()都指的是对象,所以,均不可以在static环境中使用。包括:static变量,static方法,static语句块。
  • 从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
多态

父类的引用可以指向子类 实现 动态编译。

多态存在的条件
  • 有继承关系
  • 子类重写父类方法
  • 父类引用指向子类对象
注意

多态是方法的多态,属性没有多态性

父类和子类,有联系才能转换,不然会异常!类型转换异常:ClassCastException

存在条件:继承关系,方法需要重写,父类引用指向子类对象!Father f1 = new son();

不能重写的方法:

  1. static 方法,属于类,它不属于实例
  2. final 常量 ,被final修饰的无法修改,属于常量池
  3. private 私有方法,不能被重写
方法重写 Override
概述

重写都是方法的重写,和属性无关。

重写值和非静态方法有关,静态没用,只能 Public 。

需要有继承关系,子类重写父类的方法!

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大,但不能缩小;public > protected > Default > private
  4. 抛出的异常: 范围,可以被缩小但不能扩大;ClassNotFoundException <— Exception(大)

重写,子类的方法和父类必须一致,但方法体不同!

理解

在子类继承父类时,形构相同(返回值,方法名,参数都相同)的方法会被覆盖。 但这是有前提的,他针对的是实例方法,像static这样的方法就不能被”覆盖“。

根据Java Language Specification 的描述,子类在继承父类时,对于方法而言,存在两种关系:
1.override即覆盖,这是对实例方法(instance method)而言的;子类与父类中形构相同的方法会override父类中的那个方法。

2. hide 即隐藏,这是对类方法(class method)即static方法而言的。如果子类中定义了静态方法,则它会隐藏父类中形构相同的所有方法,但如果隐藏了父类中的实例方法,则会编译报错。

根据上面的规定,“override覆盖”的前提是 实例方法,只有实例方法在继承时才会出现override情况。 如果是static方法,在继承时出现的现象根本就不能用“override”这个词描述,如果static方法在父类和子类中形构一致,则被成为 hide(隐藏)

那什么是隐藏呢?隐藏 :child隐藏了parent的变量和方法,那么,child实例就不能访问parent中被隐藏的变量或者方法,但是,将child实例向上提升转换成parent,可以访问parent中被隐藏的变量或者方法了。 我的理解是被隐藏的东西就是只和类绑定的东西。当子类继承父类,在子类对象中是访问不到父类中的被隐藏的东西的。因为这些东西只和父类绑定了。

在从动态绑定的角度来看看这个覆盖问题,因为static方法是类方法,实现时是静态绑定的(引用“JAVA 核心技术 卷1 第六版”中149页内容“private、static、final”修饰的方法是静态绑定的,所以他们修饰的方法不能实现多态,当然不需要被子类覆盖了(子类覆盖父类方法是为了实现多态)。而其他的方法在运行时动态绑定。 同时,所有的变量也都是静态绑定的。

instanceof

判断一个对象是什么类型。(类型转换—引用类型之间的转换)

  1. 父类引用指向子类的对象,不可以子类引用指向父类。
  2. 把子类转换为父类,向上转型;
  3. 把父类转换为子类,向下转型,强制转换(可能会丢失方法)
  4. 方便方法的调用,减少重复的代码,简介
static
  1. 静态变量也称为类变量,也就是直接可以被类名调用的变量。这个变量是所属于类的。
    非静态变量成为成员变量,或者实例变量,是被对象调用的,是所属具体对象的。
  2. 静态变量随着类的加载而加载,也意味着随着类的消失而消失。生命周期最长。
    实例变量,随着对象的创建而加载,随着对象的消失而消失。按照对象的生命周期而存在。
  3. 静态变量存储在方法区的静态区中。
    实例变量存在于对象所属的堆内存中。
  4. 静态变量数据,被所有对象所共享。
    实例变量是对象中的特有数据
static方法

static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。

但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。

static变量

静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。

static代码块

static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次【根据class加载原理 每个类加载一次 使用双亲委托加载】。

初始化的顺序 静态代码块 > 构造代码块 > 构造函数

静态内部类
静态导包

静态导包就是java包的静态导入,用import static代替import静态导入包是JDK1.5中的新特性。

一般我们导入一个类都用 import com……ClassName;而静态导入是这样:import static com……ClassName.;这里的多了个static,还有就是类名ClassName后面多了个. ,意思是导入这个类里的静态方法。当然,也可以只导入某个静态方法,只要把 .* 换成静态方法名就行了。然后在这个类中,就可以直接用方法名调用静态方法,而不必用ClassName.方法名 的方式来调用。

抽象类

  • abstract 修饰符可以用来修饰方法也可以修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类。
  • 抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类。
  • 抽象类必须在类前用abstract关键字修饰。因为抽象类中含有无具体实现的方法,所以一般不能用抽象类创建对象。 它是用来让子类继承的。
  • 抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
  • 子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法;否者该子类也要声明为抽象类,然后由子子类实现抽象方法。

特点

  • 抽象类不能被实例化(初学者很容易犯的错),如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。

接口

接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守

  • 普通类:只有具体实现
  • 抽象类:具体实现和规范(抽象方法)都有!
  • 接口:只有规范!自己无法写方法,专业的约束!约束和实现分离:面向接口编程

作用

  1. 约束,规范
  2. 定义一些方法,让不同的人实现。多个人完成共同的工作。
  3. 接口中所有默认的方法public abstract
  4. 所有常量默认public static final
  5. 接口不能被实例化,接口中没有构造方法。
  6. 可以实现多个接口
  7. 必须要重写接口中的方法。
  8. 声明接口interface,实现接口implements,可以实现多个方法

final

在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)

修饰类

当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。

修饰方法

注:类的private方法会隐式地被指定为final方法。

修饰变量

对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

访问修饰符

访问修饰符\作用范围所在类同一包内其他类其他包内子类其他包内非子类
private可以访问不可以不可以不可以
缺省可以可以不可以不可以
protected可以可以可以不可以
public可以可以可以可以
  • private
    被private修饰的属性和方法,不能被其他类访问,子类不能继承也不能访问。只能在所在类内部访问。
  • 缺省
    变量或者方法前没有访问修饰符时,可以被所在类访问,可以被同一包内的其他类访问 或者继承。但是不能被其他包访问。
  • protected
    被protected修饰的方法和属性,在同一包内可被访问和继承。不同包内,子类可继承,非子类不能访问。
  • public
    方法和属性前有public修饰,可以被任意包内的类访问。
    另外,类要想被其他包导入,必须声明为public。被public修饰的类,类名必须与文件名相同。

enum

定义枚举类要用关键字enum

所有枚举类都是Enum的子类

Java使用enum定义枚举类型,它被编译器编译为final class Xxx extends Enum { … }

通过name()获取常量定义的字符串,注意不要使用toString()

通过ordinal()返回常量定义的顺序(无实质意义);

枚举类的第一行上必须是枚举项,最后一个枚举项后的分号是可以省略的,但是如果枚举类有其他的东西,这个分号就不能省略。建议不要省略

枚举类可以有构造器,但必须是private的,它默认的也是private的。枚举项的用法比较特殊:枚举(“”);

枚举类也可以有抽象方法,但是枚举项必须重写该方法,使用匿名内部类的方式。

枚举在switch语句中的使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值