java学习--面向对象
对象及类的概念
对象是java程序的核心,在java程序中“万事万物皆对象”
对象可以看成是属性和方法的封装体
类是用来创建同一类型的对象的模板,在一个类中定义了该类对象所应具有的属性和方法
J2SDK提供了很多类供变成人员使用,编程人员也可以定义自己的类
面向对象的编程------一组对象互相配合通过沟通完成特定的功能
引用-----引用是java面向对象基本概念,java中除基本类型之外的变量类型都称之为引用类型。java中的对象是通过引用对其操作的
类的定义主要有两方面组成:属性和方法
属性
属性可以使用java语言中的任何一种数据类型(包括基本类型和引用类型)
在定义属性时可以对其初始化,如果不对其初始化,java使用相应数据类型默认的值对其初始化
属性的作用范围为整个类体
方法
必须设置返回值类型(构造方法除外),如果没有返回值,则返回值类型为void
实参的数目,类型以及次序必须和形参一致
如果方法有返回值(即返回值类型不是void),则必须保证方法体一定会调用return语句,如果return后为变量,则要保证该变量一定会被初始化。
参数传递原则:基本类型传递的是该数据值本身。引用类型传递的是对对象的引用,而不是对象本身
如何在内存中区分类和对象
类是静态的概念,位于方法区
对象是new出来的,位于堆内存,
类的每一个非静态属性在不同的对象中有不同的值保存在该对象的堆区,不共享
类的静态属性被所有的对象共享,值位于方法区
类的所有方法被所有的对象共享,位于方法区,方法只有在执行的时候占用内存
个人推断和理解(仅为了理解,不一定对)
假设我们将一个变量名中当前保存的值为当前值,当当前值的数据为基本类型时,则最终值即为当前值
当当前值为一个引用时,则最终值为引用所指向的值
方法名,属性名也可以看作变量
在new出一个对象时,类中所有的属性名和方法名在该对象中都有。
只是静态属性名和方法名(静态和非静态)的当前值都为引用,且引用固定不可变化,固定指向该类的静态属性和方法的区域,所以该类new出的所有对象的静态属性和方法名的最终值都为该类的静态属性和方法。
对于非静态属性,其当前值可以为基础类型和引用类型,非静态属性的当前值为引用时,他的引用是变化的,不固定的,可以指向不同的区域
比如A类对象1的非静态属性可以指向B类对象1的区域,也可以值像B类对象2的区域,A类对象2的非静态属性同样
但A类对象1的静态属性和方法只能唯一固定指向方法区A类的静态属性和方法区域
所以一个类的静态属性和方法被该类所有的对象所共享
虽然静态方法和非静态方法都被共享,但静态方法可以通过类名直接调用,且静态方法中只能使用静态属性
因为方法只有在执行时才会占用堆栈内存,此处的共享指的是共享方法区方法定义的,并不共享执行时堆栈内存。同一方法的每一次调用都会占用不同的堆栈内存
而静态属性的调用不会再使用额外的堆栈内存
对象的创建
必须使用new关键字创建对象(?)
构造方法
构造方法是定义在java类中用来初始化该类对象的方法
构造方法与类名相同
构造方法没有返回值
一个类可以通过重载的方式定义多个构造方法
如果不显示的定义构造方法,那么编译器会为该类自动添加形如 类名 () {} 的构造方法
继承类(子类)的构造方法
子类的构造方法中必须调用其父类的构造方法(显示的调用或者默认调用无参的父类构造方法)
如果子类的构造方法中没有显示的调用父类的构造方法,则系统会默认调用父类的无参数构造方法
如果子类的构造方法中没有显示的调用父类的构造方法,而父类中又没有无参的构造方法,则编译出错
子类的构造方法可以使用 super(argument_list) 来显示的调用父类的构造方法,且必须写在子类构造方法的第一行
可以使用this(argument_list) 来调用本类其他的构造方法
约定俗成的命名规则
类名的首字母大写
变量名和方法名的首字母小写
都运用驼峰标识
方法的重载
方法的重载是指一个类中可以有相同名字,但参数不同的多个方法。调用时,会根据不同的参数表选择出对应的唯一方法。
参数不同指的是参数的类型,个数或者次序的不同
普通的方法和构造方法都可以重载
Object类
Object类是所有java类的根基类(所有的类都直接或者间接继承Object类,所以Object变量引用可以指向所有类型的对象)
如果在类的声明中未使用extends关键字指明其根基类(父类),则默认继承Object类
对象转型
父类引用可以指向子类对象。(object类的引用可以指向所有的对象,因为Object类是所有java类的根基类)
虽然父类引用可以指向子类对象,但只能访问父类所应有的属性和方法,包括子类重写的方法,却不能访问子类相对于父类新增加的属性和方法。
父类引用指向的子类对象要想访问子类新增加的属性和方法,则必须进行强制转换,强制转换成子类引用指向子类对象后才可以访问。
可以使用instanceof来判断引用类型变量所指向的对象是否属于该类或者该类的子类
动态绑定和多态
动态绑定和多态是指在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际类型调用其相应的方法(子类继承或者重写的方法)
也就是说,父类引用指向子类对象调用方法(只能调用父类所具有的方法)时,会判断该对象的实际类型,若实际类型重写了父类的方法,则调用重写后的方法,否则调用继承于父类的方法。
父类引用指向子类对象只能访问父类拥有的属性和方法,而无法访问子类独有的属性和方法。只是如果子类重写了父类的方法,实际上调用的是子类重写后的方法,而不是父类的方法
需要注意,如果子类重写了父类已具有的某个属性,父类引用指向子类对象访问该属性时,实际上是调用父类的属性,而不是子类重写的属性,这点与重写的方法不同,也就是说动态绑定和多态只是针对重写的方法,而不针对重写的属性
一般情况下子类不会重写父类的属性,但写了也不会报错,但某些场合子类是不能重写父类的属性的,否则会报错。例如Gson类的toJson方法中传入子类重写父类属性的子类对象时,就会报错
多态:同一类型的引用变量,调用同一个方法是,执行过程却不相同
多态的条件:1,要有继承 2,多个继承类要重写父类的方法 3, 使用父类引用指向子类对象并调用重写方法
这样同一个父类引用可以指向其多个子类的对象,当使用父类引用来调用方法时,真正执行的是子类重写的方法,子类重写的方法各不相同,这就构成了多态
抽象类
用abstract关键字来修饰一个类时,这个类叫做抽象类。
用abstract来修饰一个方法时,这个方法叫做抽象方法。
抽象类不能被实例化,只能被继承
抽象方法不能有方法体,只能被继承类重写
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
final关键字
final修饰的变量的值不能被改变
final修饰的方法不能够被重写
final修饰的类不能够被继承
接口
接口是抽象方法和常量值的集合
从本质上将,接口是一种特殊的抽象类,这种抽象类中只包含类常量和方法的定义,而没有变量和方法的实现
接口的特性
多个无关的类可以实现同一个接口
一个类可以实现多个无关的接口
与继承类似,接口与实现类之间存在多态性
接口可以继承其他的接口,并添加新的属性和抽象方法
接口中的属性只能为常量,修饰符默认为public static final,也只能是public static final
接口中的方法只能是抽象方法,修饰符默认为public,也只能是public