疯狂Java讲义读书笔记05 面向对象-上

Java语言里定义类的简单语法如下:

 

 构造器是一个类创建对象的根本途径,如果一个类没有构造器,这个类通常无法创建实例。因此,Java语言提供了一个功能:如果程序员没有为一个类编写构造器,则系统会为该类提供一个默认的构造器。一旦程序员为一个类提供了构造器,系统就不会再提供构造器。

在类中定义的成员static相当于一个标志,有static修饰的成员属于类本身,没有static修饰的成员属于该类的实例。

构造器既不能指定定义返回值类型,也不能使用void。因为构造器实际上是有返回值的,构造器返回的是该类的实例,可以把这个类的实例当成构造器的返回值。

构造器的返回值是隐式的。

 

Java提供了一个this关键字,this关键字总是指向调用该方法的对象。

大部分时候,一个方法访问该类定义的其他方法、成员变量时不加this前缀的效果是一样的。

对于static修饰的方法而言,则可以使用类来直接调用该方法,如果在static修饰的方法中使用this关键字,则这个关键字就无法指向合适的对象。所以,static修饰的方法中不能使用this引用,所以static修饰的方法不能访问不使用static修饰的普通成员,因此Java语法规定:静态成员不能直接访问非静态成员。

省略this前缀只是一种假象。

方法不能独立存在,方法必须属于类或对象。

因此如果需要单独定义方法,则只能在类体内定义,不能独立定义一个方法。

Java里的方法不能独立存在,它必须属于一个类或一个对象,因此方法也不能像函数那样被独立执行,执行方法时必须使用类或对象作为调用者。

永远不要把方法当成独立存在的实体,正如现实世界由类和对象组成,而方法只能作为类和对象的附属,Java语言里的方法也是一样。

 

成员变量指的是类里定义的变量

局部变量指的是方法里定义的变量

 

 

隐藏和封装

封装是面向对象的三大特征之一(另外两个是继承和多态),它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是提供该类提供的方法来实现对内部信息的操作和访问。

封装是面向对象语言对客观世界的模拟,在客观世界里,对象的状态信息都被隐藏在对象内部,外部无法直接操作或修改,就如刚刚说的Person对象的age变量,只能随着岁月的流逝,age才会增加,通常不能随意修改Person对象的age。

对一个类或对象实现良好的封装可以实现以下的目的

隐藏类的实现细节

让使用者只能通过事先预定的方法来访问数据,从而在该方法里加入控制逻辑,限制对成员变量的不合理访问

可进行数据检查,从而有利于保证对象信息的完整性。

便于修改,提高代码的可维护性

 

封装有两层含义:

把该隐藏的隐藏起来,把该暴露的暴露起来。这两个方面都需要通过使用Java提供的访问控制符来实现。

 

 其中default是包访问权限

 

 Java类的实例变量的setter和getter方法有非常中哟的意义

例如某个类里包含了一个名为abc的实例变量,则其对应的setter和getter方法名应为setAbc和getAbc

如果一个Java类的每个实例变量都被private修饰,并为每个实例变量都提供了public修饰setter和getter方法。

那么这个类就是一个符合JavaBean规范的类,因为JavaBean总是一个封装良好的类。

 

类里绝大部分成员变量都应该使用private修饰,只有一些static修饰的、类似全局变量的成员变量才可能考虑使用public修饰。除此之外,有些方法只用于辅助实现该类的其他方法,这些方法被称为工具方法,工具方法也应该用private修饰。

如果某个类主要作为其他类的父类,该类里包含的大部分方法可能仅仅希望被子类重写,而不希望被外界直接调用,则应该使用protected修饰这些方法。

希望暴露出来给其他类自由调用的方法应该使用public修饰,因此,类的构造器通过使用public修饰,从而允许在其他地方创建该类的实例。因为外部类通常都希望被其他类自由使用,所以大部分外部类都使用public修饰。

 

super限定

如果需要在子类方法中调用父类被覆盖的实例方法,则可以使用super限定来调用父类被覆盖的实例方法。

为了在子类方法中访问父类中定义的,被隐藏的实例变量,或为了在子类方法中调用父类中定义的、被覆盖的方法,可以通过super作为限定来调用这些实例变量和实例方法。

 

 

多态

Java引用变量有两个类型:一个是编译时类型,一个是运行时类型

编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋予该变量的对象决定。

如果编译时类型和运行时类型不一样,就很有可能出现所谓的多态。

 

 与方法不同的是,对象的实例变量不具备多态性,编译时的类型的实例变量是多少就是多少。

引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法。

通过引用变量来访问其包含的实例变量时,系统总是试图访问它编译时类型所定义的成员变量,而不是它运行时所定义的成员变量。

 

引用变量的强制类型转换

引用类型之间的强制类型转换只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时就会出现错误。如果试图将一个父类实例转换成子类实例,则这个对象必须实际上是个子类实例才行(即编译时类型为父类类型,而运行时类型是子类类型),否则将在运行时引发classcastexception

instanceof运算符的作用是:在进行强制类型转换前先判断前一个对象是否是后一个类的实例,保证了健壮性。

 

 

初始化块:前面定义的初始化块先执行、后面定义的初始化块后执行

 

 

初始化块的修饰符只能是static,使用static修饰的初始化块称为静态初始化块。初始化块里的代码可以包含任何可执行性语句,包括定义局部变量、调用其他对象的方法,以及使用分支、循环语句等。

初始化块只在创建Java对象时隐式执行,而且在执行构造器前执行。

虽然Java运行一个类里定义两个初始化块,但这没有任何意义,因为初始化块是在创建Java对象时隐式执行的,而且总是全部执行。

当Java创建一个对象时,系统先为该对象的所有实例变量分配内存,接着程序开始为这些实例变量执行初始化,先执行初始化块或声明实例变量时指定的初始值,再执行构造器里指定的初始值。

普通初始化块、声明实例变量指定的默认值都可以认为是对象的初始化代码,它们执行顺序与源代码中的排列顺序相同。

 

从某种角度看,初始化块是构造器的补充,初始化块总是在构造器执行之前执行。系统也同样可使用初始化块来进行对象的初始化操作。

实际上初始化块是一个假象,使用javac命令后编译Java类后,该Java类中的初始化块会消失,初始化块中的代码会被还原到每个构造器中,且位于每个构造器前面。

 

 

静态初始化块:

如果定义的初始化块使用了static修饰符则这个初始化块就变成了静态初始化块,也被称为类初始化块。

静态初始化块是类相关的,用于对整个类进行初始化处理,通常用于对类变量执行初始化处理。静态初始化块不能对实例变量进行初始化处理。

 

posted @ 2020-01-30 21:02  chyblogs  阅读(97)  评论(0)    收藏  举报