资讯专栏INFORMATION COLUMN

java面向对象(上)

liaosilzu2007 / 3471人阅读

摘要:根据出现的位置,作为对象的默认引用有两种情形构造器中引用该构造器正在初始化的对象。在构造器中代表该构造器正在初始化的对象。用于限定该对象调用它从父类得到的实例变量和方法。

子类继承父类就可以继承到父类的成员变量和方法。如果访问控制允许,子类实例可以直接调用父类里定义的方法。

如果多个重载的构造器里包含了相同的初始化代码,则可以把这些初始化代码放置在普通代码块里完成,初始化块总在构造器执行之前被调用。

静态初始化块用于初始化类,在类初始化阶段被执行。

如果继承树里的某一个类需要被初始化时,系统将会同时初始化该类的所有父类。

类和对象

Static修饰的成员表明它属于这个类本身,而不属于该类的单个实例,因为通常把static修饰的成员变量和方法也称为类变量,类方法。

通常把不使用static修饰的成员变量和方法也称为实例变量和实例方法。

静态成员不能直接访问非静态成员。

Static真正的作用就用于区分成员变量,方法,内部类,初始化块这四种成员到底属于类本身还是属于实例。

产生的实例变量是在内存中存储的。

引用变量里存放的仅仅是一个引用,他指向实际的对象。

This关键字总是指向调用该方法的对象。

根据this出现的位置,this作为对象的默认引用有两种情形:

- 构造器中引用该构造器正在初始化的对象。
- 在方法中引用调用该方法的对象。

This可以代表任何对象,当this出现在某个方法体中时,他所代表的对象是不确定的,但它的类型是确定的:他所代表的只能是当前类的实例,只有当这个方法被调用时,他所代表的对象才被确定下来,谁在调用这个方法,this就是谁。

Static修饰的方法中不能使用this引用。

静态成员不能访问非静态成员。

Java编程中不要使用对象去调用static修饰的成员变量,方法,而是应该使用类去调用static修饰的成员变量,方法。

如果确实需要在静态方法中访问另一个普通方法,只能创建对象。

如果方法中有个局部变量和成员变量同名,但程序又需要再该方法里访问这个被覆盖的成员变量,则必须使用this前缀。

This在构造器中代表该构造器正在初始化的对象。

实例方法必须使用对象调用。

   public class A {
       int a  =  123;
       public A() {
           System.out.println("构造A");
           System.out.println(this.a);
       }
   }
   public class B extends A {
       int a = 456789;
       public B() {
           System.out.println("构造b");
           System.out.println(this.a+"BBB");
       }
       public static void main(String[] args) {
           new B();
       }
   }
   
   构造A
   123
   构造b
   456789BBB
   

方法详解

同一个类的一个方法调用另一个方法时,如果被调方法是普通方法,则默认使用this作为调用者。如果被调方法是静态方法,则默认使用类作为调用者。

Java里方法的传递方式只有一种:值传递。所谓值传递就是将实际参数值的副本传入方法内,而且参数本身不会收到任何影响。

Java中的基本类型的参数传递,和引用类型的传递都是值传递,对于引用类型的传递也是将原来的对象的地址复制一份给参数,这时候就是原来对象和参数的地址是一样的,都指向了同一个堆内存中的对象,对原来对象或者参数任何一方赋值null都不会影响另一方。

数组形式的形参可以处理形参列表的任意位置,但和数可变的形参只能处于形参列表的最后。

递归一定要向已知方向递归。

一个类中包含了两个或者两个以上的方法名相同而形参不同则被称为方法重载。

如果需要调用test(String ...
books)方法,又只想传入一个字符串参数,则可采用传入字符串数组的形式:object.test(new
String[]{“TEST”});

方法重载的要求:同一个类中方法名相同,形参列表不同。

Java中不能使用方法返回值类型作为区分方法重载的依据。

成员变量和局部变量

成员变量指的是在类里定义的变量,也就是field,局部变量就是在方法里定义的变量.

所有变量
成员变量
实例变量,不以static修饰
类变量,static修饰的
局部变量
代码块局部变量,在代码块中定义的
方法局部变量,在方法内定义
形参,方法签名中定义的变量

类变量从该类的准备阶段起开始存在,直到系统完全销毁这个类,类变量的作用域与这个类的生存范围相同;而实例变量则从该类的实例被创建起开始存在,知道系统完全销毁这个实例,实例变量的作用域与对应实例的生存范围相同。

成员变量无需显示初始化,只要为了一个类定义了类变量或实例变量,系统就会在这个类的准备阶段或者创建该类的实例时进行默认初始化,成员变量默认初始化时的赋值规则与数组动态初始化时数组元素的赋值规则完全相同。

与成员变量不同的是,局部变量除形参之外,都必须显示初始化。必须先给方法局部变量和代码块局部变量指定初始值,否则不可以访问他们。

当系统加载类或者创建该类的实例时,系统自动为成员变量分配内存空间,并在分配内存空间后,自动为成员变量指定初始值。

在程序中使用局部变量,也应该尽可能的所有局部变量的作用范围,作用范围越小,他在内存中停留的时间也就越短,程序运行性能就越好。

什么情况下考虑使用成员变量??

如果需要定义的变量是用于描述某个类或某个对象的固有信息,例如人的身高,因为每个人都必须具有这些信息,这时候就可以定义成成员变量,如果此变量对于这个类的所有实例都是相同的,如眼睛的数量,那么他就可以考虑定义成为类变量。

如果某个类中需要以一个变量来保存该类或者实例运行时的状态信息,例如五子棋棋盘的数组,这种用于保存某个类或某个实例状态信息的变量通常应该使用成员变量。

如果某个信息需要在某个类的多个方法之间进行共享,则这个信息应该使用成员变量来保存。

隐藏和封装

为了实现良好的封装,需要考虑两方面

将对象的成员变量和实现细节隐藏起来,不允许外部直接访问。

把方法暴露出来,让方法来控制对这些成员变量进行安全的访问和操作。

访问控制修饰符

private:当前类访问权限

default:包访问权限

protected:子类访问权限

public:公共访问权限

访问控制修饰符的使用原则

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

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

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

JDK 1.5增加了静态导入import static * ,用于导入制定类的某个静态成员变量,方法或全部的静态成员变量,方法。

使用import可以省略写包名,import static 则连类名都可以省略。

深入构造器

当系统开始执行构造器的执行体之前,系统已经创建了一个对象,只是这个对象还不能被外部程序访问到,只能在该构造器中通过this来引用。当构造器的执行体执行结束后,这个对象作为构造器的返回值被返回,通常还会赋给另一个引用类型的变量,从而让外部程序可以访问该对象。

如果两个构造器中有相同的代码,可以提取相同的代码到一个构造器,另一个构造器中用this来引用相同代码的构造器。

类的继承

方法的重写要遵循“两同两小一大”规则,两同即方法名相同,参数列表相同,两小即子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类型比父类方法抛出的异常更小或相等,一大是子类方法的访问权限应该比父类方法的访问权限更大或相等。

在子类中调用父类中被覆盖的方法,则可以使用super或者父类类名作为调用者来调用父类中被覆盖的方法。

重载主要发生在同一个类的多个同名方法之间,重写发生在子类和父类的同名方法之间。

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

Super用于限定该对象调用它从父类得到的实例变量和方法。This和super 都不可以出现在类方法中。

如果在某个方法中访问名为a的成员变量,但是没有显示指定调用者,那么系统的查找顺序为:

查找该方法中是否有名为a 的局部变量

查找当前类中是否有名为a 的成员变量

查找a的直接父类中是否包含a的成员变量,依次上溯a的所有父类,未找到则编译出错。

当程序创建一个子类对象时,系统不仅会为该类中定义的实例变量分配内存,也会为它从父类继承得到的所有实例变量分配内存,即使子类定义了与父类同名的实例变量。

子类调用父类构造器的情况

子类构造器显示使用super来指定执行的父类构造器。

子类构造器中使用this来调用其它构造器,程序会执行另一个构造器之前调用父类构造器。

没有super和this显式调用,会默认调用父类的无参构造。

创建任何对象总是从该类所在继承树最顶层类的构造器开始执行,然后依次向下执行,最后才执行本类的构造器。

Java引用变量有两种类型:一种是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定。运行时类型由实际赋给该变量的对象决定,这就是所谓的多态。

对象的实例方法具有多态性,对象的实例变量则不具备多态性。

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

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

强制类型转换:基本类型之间的转换只能在数值类型之间进行,引用类型之间的转换只能在具有继承关系的两个类型之间转换。

Instanceof用于判断前面的对象是否是后面的类。Instanceof运算符前面操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系。A是否是B的子类。

继承和组合

继承带来的最大坏处就是破坏封装。

设计父类遵循的规则

尽量隐藏父类的内部数据,尽量所有的成员变量都用private修饰,不会被子类随意改变。

不要让子类可以随意访问,修改父类的方法。父类中那些仅为辅助其他的工具方法,应该使用private修饰,如果希望被外部类调用,那么就使用public修饰,如果不希望子类重写该方法,加final,如果允许子类重写,那么protected。

尽量不要再父类构造器中调用将要被子类重写的方法。

何时需要从父类派生新的子类问题??

子类需要额外增加属性,而不仅仅是属性值的改变。例如person 派生出student。

子类需要增加自己独有的行为方式,包括增加新的方法或重写父类的方法。

组合就是用一个个的类来描述一个整体的各个部分,然后用零散的类来组成一个完整的整体,对这个类进行更详尽的描述。

用继承还是组合??

对于Cat和Animal,继承显然更加合适,因为用一个动物组成一个Cat毫无意义,继承是is-a关系,组合是has-a关系。

初始化块

初始化块的修饰符只能是static,使用static修饰的代码块叫做静态初始化块,里面可以包含任何可执行语句。

当java创建一个对象时,系统先为该对象的所有实例变量分配内存,前提是该类已经被加载过了,接着程序开始对这些实例变量执行初始化,其初始化顺序是,先执行初始化块或者声明实例变量时制定的初始值,在执行构造器里制定的初始值。

初始化块总是在构造器之前执行。

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

系统将会在类初始化阶段执行静态初始化块,而不是在创建对象的时候才执行,因此静态初始化块总是比普通初始化块先执行。

Java系统加载并初始化某个类时,总是保证该类的所有父类全部加载并初始化。

当JVM第一主动使用某一个类时,系统会在类准备阶段为该类的所有静态成员变量分配内存,在初始化阶段则负责初始化这些静态成员变量,初始化静态成员变量就是执行类初始化代码或者声明类成员变量时制定的初始值,他们的执行顺序与源代码中的排列顺序相同。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69293.html

相关文章

  • Java学习笔记——面向对象

    摘要:对象既是该类事物实实在在存在的个体。类与对象的关系图类就是汽车汽车就是堆内存中的对象。成员变量成员变量成员函数的车,轮胎数个,跑起来了对象的创建创建对象中创建对象,使用关键字在堆内存中开辟了空间,产生了一个实体。 声明:本文首发于我的个人微信公众号【Java编程社区】,查看更多文章与学习资源请移步我的公众号Java编程社区 万物皆对象 学习Java,我们都听过这句话:万物皆对象。那么什...

    DoINsiSt 评论0 收藏0
  • 7. 初步理解面向对象 【连载 7】

    摘要:是一种典型的面向对象编程语言。这篇文章主要是来初步理解一下面向对象的思维为下面的内容先给一个基础。针对面向对象编程的更多内容,会在后面的文章里面详细解释。他们都称之为对象。之后,我们再用编程语言,把这种映射编写出来,就是的面向对象编程啦。 showImg(https://segmentfault.com/img/remote/1460000012983458?w=900&h=500);...

    keelii 评论0 收藏0
  • 谈谈我所理解的面向对象

    摘要:众多面向对象的编程思想虽不尽一致,但是无论哪种面向对象编程语言都具有以下的共通功能。原型编程以类为中心的传统面向对象编程,是以类为基础生成新对象。而原型模式的面向对象编程语言没有类这样一个概念。 什么是面向对象?这个问题往往会问到刚毕业的新手or实习生上,也是往往作为一个技术面试的开头题。在这里我们不去谈如何答(fu)好(yan)问(guo)题(qu),仅谈谈我所理解的面向对象。 从历...

    avwu 评论0 收藏0
  • 夯实Java:从面向对象说起

    摘要:面向对象与面向过程的区别要知道,二者并不是非此即彼,而是相辅相成的。而面向过程,则在微观上对对象内部进行具体的实现。面向对象的三大特性说到面向对象,就不得不说其三大特性封装继承和多态。封装封装是面向对象最基础的特性。 作者:伯特出处:github.com/ruicbAndroid/LoulanPlan声明:本文出自伯特的《LoulanPlan》,转载务必注明作者及出处。 刚学习 Jav...

    hearaway 评论0 收藏0
  • Java知识点总结(面向对象

    摘要:知识点总结面向对象知识点总结面向对象面向对象概念是相对于面向过程而言,过程其实就是函数,对象是将函数和属性进行了封装。指向了该对象关键字代表对象。静态变量所属于类,所以也称为类变量成员变量存在于堆内存中。 Java知识点总结(面向对象) @(Java知识点总结)[Java, Java面向对象] [toc] 面向对象概念 是相对于面向过程而言,过程其实就是函数,对象是将函数和属性进行了封...

    itvincent 评论0 收藏0
  • 超详细的Java面试题总结(一)之Java基础知识篇

    摘要:最近在备战面试的过程中,整理一下面试题。成员变量如果没有被赋初值,则会自动以类型的默认值而赋值一种情况例外被修饰但没有被修饰的成员变量必须显示地赋值而局部变量则不会自动赋值。   最近在备战面试的过程中,整理一下面试题。大多数题目都是自己手敲的,网上也有很多这样的总结。自己感觉总是很乱,所以花了很久把自己觉得重要的东西总结了一下。 面向对象和面向过程的区别 面向过程:  优点:性能比面...

    vpants 评论0 收藏0

发表评论

0条评论

liaosilzu2007

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<