面向对象(二) 一、继承 1.继承概述将多个类的共性抽取出来,形成一个父类。让所有具备这些共性属性的类,继承这个父类,成为其子类。这样做的好处在于:1)这样可以避免重复代码,提高代码复用性;2)继承是面向对象另一特点多态的基础之一,有了继承,才有多态;3)同时可以使子类的功能更加强大灵活,便于扩展 注意:1)不要仅为了获取其他类的功能,而使用继承;必须在类与类之间有所属关系的情况下,才使用继承; 2)Java中只支持单继承。因为多继承容易带来安全隐患。如果支持多继承,多个父类当中有相同名字的不同功能的方法,子类在调用同名方法的时候,虚拟机不能确定要运行哪个; 3)Java中保留了多继承的机制,用多实现的方式来体现(implements); 4)Java支持多层继承,C继承B,B继承A,以此类推,形成一个继承体系。继承体系相对复杂,想要良好运用该体系,先查阅体系中父类的描述,通过了解父类中的共性功能,就能了解该继承体系的基本功能。在具体调用时,应创建最小子类的对象。由于:1> 父类不能创建对象,如抽象类;2> 子类对象有更多的功能,包括父类和自由的功能 2.继承的表现形式类与类之间不止有A属于B这一种关系,还有聚集的关系。聚集关系分为:1)聚合关系:A由B组成,B是A中的一个,但是缺少一个B,不影响A的整体功能;例如:球队由球员组成,一个球员是球队的一员;2)组合关系:A由B组成,B是A的一部分,缺少B,A的功能将受到极大影响;例如:心脏是人的一部分 3.继承的应用1)super关键字1> super关键字和this关键字的用法基本一致;2> this代表本类对象的引用,super代表父类对象的引用 2)这一小节探讨继承关系出现后,类中成员的变化1> 变量的变化 示例代码: 继承状态下,成员变量内存加载图示: 继承状态下,成员变量的变化如下:如果子类和父类中出现非私有同名变量,子类要访问本类中的同名变量,用this关键字;子类要访问父类中的同名变量,用super关键字。 小扩展:继承的时候,子类继承父类的成员变量,同时继承该成员变量的值。 示例代码: 2> 方法的变化 示例代码: 继承状态下,成员方法的变化如下:当子类出现和父类一模一样的方法时,子类对象调用同名方法,会运行子类方法的内容。由于子类继承了父类的方法,但是子类在具体实现的时候需要有不同的功能,这个时候,只需要用到方法的另一个特性:复写。在子类中定义一个和父类完全相同的方法,在方法体中实现子类的特有功能即可。如果要在子类的复写方法中,调用父类的方法,只需要加上super.方法名即可。 小扩展:super关键字的使用 示例代码: 子类对象调用show()方法时,上述代码既输出”Parent show”,也输出”Sub show”。 复写注意事项:a. 复写成功必须保证子类方法权限大于等于父类方法权限;b. 静态方法只能复写静态方法;c. 复写和重载的区别在与,复写要求子类父类方法一模一样,重载要求同名函数的参数列表不一样 3> 构造方法的变化 示例代码: 子类对象进行初始化时,父类的构造方法也会执行。因为子类的构造方法第一行默认写有隐式语句super();super()会访问父类中空参数的构造方法。super();存在于所有子类的所有构造方法的第一行。如果访问父类中指定的构造方法,只需通过手动定义super语句。 子类一定要访问父类构造方法的原因:由于子类继承了父类的成员,子类对象在被创建时,应该先知道父类是如何对其成员进行初始化的,以避免代码功能的重复。 注意:构造函数中,this和super只能存在一个,因为两者都必须写在构造方法第一行。 二、final关键字 1.final的定义及特点final作为一个修饰符:1)可以修饰类,变量以及方法;2)被final修饰的类不能被继承;3)被final修饰的方法不能被复写;4)被final修饰的变量是常量,值不能被改变;既可以修饰成员变量,也可以修饰局部变量;5)内部类定义在类中的局部位置上时,只能访问该局部被final修饰的局部变量 示例代码: 三、抽象类 1.抽象的定义抽象就是将多个事物的共性的、本质的内容进行抽取和概括。例如:老虎,猫,狮子都是猫科动物,猫科就是一个抽象的概念。 2.抽象类抽象类是包含抽象方法的类。抽象方法只有方法的定义,没有方法体。抽象方法的具体实现,有子类复写完成。抽象方法只负责抽象出不同对象的共性,但是不涉及具体实现的细节。例如:猫和狗都会叫,但是叫的内容不同。抽象方法定义一个叫的功能,具体叫的内容则有子类对象来实现。 3.抽象类的特点1)抽象方法一定定义在抽象类中;2)抽象方法和抽象类都被abstract关键字修饰;3)抽象类不可以实例化;4)抽象类中的抽象方法要被使用,必须由子类复写其所有抽象方法,由子类对象进行调用;如果子类中只覆盖了部分抽象方法,那么该子类还是一个抽象类;5)抽象类中可以不定义抽象方法,仅为了让该类不被实例化 代码示例: 4.抽象类练习1)练习1:开发一个系统需要对员工进行建模,员工包含3个属性:姓名,工号以及工资;经理也是员工,除了含有员工的属性外,另外还有一个奖金属性。请使用继承的思想设计出员工类和经理类。 示例代码: 2)练习2:模版方法模式使用System类中的currentTimeMillis()方法获取一段程序运行的时间。 示例代码: 如果GetTime类要被其他程序使用,来获取程序运行时间,那么该类中所要运行的程序代码是不确定的。因此,首先将要运行的代码提取出来,封装在一个方法中。 示例代码: 现在想运行另外一段代码,直接修改源代码的方式操作性极差。那么可以运用一个类,继承GetTime类,然后以复写runCode()方法的方式更改要运行的代码,并在主函数中创建子类的对象,调用getTime()方法即可。 示例代码:…
Tag: Java
Java基础—面向对象(一)
面向对象(一) 一、理解面向对象 面向对象作为一种编程思想,其本质是基于面向过程的。相对于强调功能行为的面向过程变成方式而言,面向对象强调的是功能的封装,形成具备一定功能的对象。面向对象的思维方式,符合人们的思考习惯,可以将复杂的事情简单化。从面向过程到面向对象,程序员完成了从执行者到指挥者的角色转变。 在使用面向对象概念的时候:1.先找具有所需要功能的对象是否存在,存在即可使用;2.如果不存在,那么创建一个具备所需功能的对象;3.创建具备不用功能对象的过程,就是简化开发,提高代码复用性的过程 二、面向对象的特征: 1.封装:Java的封装是一种信息隐藏技术,将属性和方法封装在一个类当中,只对调用者开放相应接口来访问该类的成员属性和方法。封装提高了程序的复用性和可维护性; 2.继承:Java的继承特性,能使一个派生类类拥有其父类的属性和方法,并扩展其特有的方法; 3.多态:指允许不同类的对象对同一方法做出不同响应。即同一方法可以根据调用对象的不同而表现出多种不同的行为方式。多态的发生必须满足1)继承;2)复写;3)父类引用指向子类对象;这三个条件 三、类与对象的关系 Java中通过定义类的形式,来描述生活中的具体事物。类是具体事物的抽象定义。对象则是该类在生活中的具体体现,是实实在在的个体。 四、类的定义 生活中描述事物,就是要描述事物的不同属性和行为。如:人有身高,体重,年龄等属性;有起床,刷牙等行为。在Java中,用类(class)来描述事物。 属性:就是类中声明的成员变量;行为:就是类中声明的成员方法; 定义一个类,其实就是在定义类中的成员变量和成员方法。 类的示例代码: 创建对象的代码示例: 该对象的内存结构图如下: 当new一个Car对象的时候:1.在堆内存中开辟空间,储存Car()对象及其成员变量color,num;2.将内存地址赋给栈内存中该对象的引用c1,c1即指向Car()对象;3.c1修改color的值,将新值赋给color 五、成员变量和局部变量的不同 1.作用域不同:1)成员变量作用域为整个类;2)局部变量作用域为方法或者语句 2.在内存中的位置不同:1)成员变量在堆内存中;对象实例被new出来之后,才开辟内存空间给成员变量;2)局部变量在栈内存中 六、匿名对象: 1.应用一: 如果使用多个匿名对象,第一行执行完之后,由于没有引用指向这个对象,该对象立刻成为垃圾,等待回收。 用匿名对象调用方法是通常做法,调用成员属性没有意义。所以,当对对象方法只调用一次时,可以用匿名对象完成。如果对对象进行多个成员调用,必须给这个对象起名字。 2.应用二:将匿名对象作为实际参数进行传递。 不使用匿名对象作为参数的示例代码: 上述代码内存运行过程如图: 运行过程:1.将创建的对象的内存地址赋给引用c,c即指向该对象;2.将引用c传给该对象的show()方法,即将该对象的地址赋给show()方法的参数c,show()方法中的参数c即指向该对象;3.show()方法访问该对象的成员变量 使用匿名对象作为参数的示例代码: 上述代码内存运行过程如图: 使用匿名对象作为参数,直接将对象地址赋给show()方法的参数c,c再访问该对象的成员变量。 七、封装 1.定义封装是指,隐藏对象的属性和实现细节,仅对外提供公共访问方式。 2.封装的好处1)类的内部变化被隔离,调用者无须知道这些变化,照样能实现功能;2)类内部细节的实现无须调用者了解,便于使用;3)封装的代码可以被不同调用者使用,提高复用性;4)不想对外开放的属性,通过封装能很好隐藏起来,提高安全性 3.private关键字private:用于修饰类中的成员变量和成员方法,被修饰的成员只能在本类被访问。private是封装的一种表现形式。当使用private修饰成员变量后,应设置相应的get和set方法,让外部访问私有变量。 示例代码: 八、构造方法 1.构造方法特点1)方法名与类名相同;2)不用定义返回值类型;3)不可以写return语句;4)在创建对象的时候,自动调用 2.构造方法的作用构造方法可以对对象进行初始化。对象在创建的时候,就应该具备其基本特性。构造方法就初始化了这些基本特性。 3.构造方法小细节1)当一个类中没有定义构造方法时,Java默认会为该类加入一个空参数的构造方法;2)当在类中声明了自定义的构造方法后,Java不再为该类添加构造方法;3)对象创建时就具备的特性和行为,可以定义在构造函方法中,以便创建时初始化;4)构造方法中初始化过了的私有变量,还是需要定义set和get方法,因为在对象的使用过程中,可能涉及改变其私有变量的值,此时就要用到set方法,获取该私有变量的值,需要用到get方法 示例代码: 九、构造代码块 1.构造代码块的定义构造代码块是定义在类中的一个独立代码区间。构造代码块的作用是为对象进行初始化。对象一旦创建就立刻运行构造代码块,且运行优先级高于该类的构造方法。 2.构造代码和构造方法的区别1)构造代码是给所有对象进行统一初始化;2)构造方法是给对应的对象初始化 3.构造代码块的应用将所有对象的共性属性或行为定义在构造代码块中,那么所有对象创建的时候同一执行构造代码块中的内容。 示例代码: 十、this关键字 1.this的概念this关键字代表调用this所在方法的对象的引用,即哪个对象调用了this所在的方法,this就指向那个对象。 2.this关键字的应用1)this关键字用于区分局部变量和成员变量重名的情况;并且,定义类中方法时,如果需要在方法内部使用本类对象的时候,用this指向这个对象 示例代码: 2)this关键字可以用于构造方法间互相调用 示例代码: 3)注意:this关键字调用其他构造方法的语句只能写在构造方法的第一行,因为初始化动作要先执行 十一、static关键字…
Java基础—数组
一、数组的定义 1.数组的概念数组是同一种类型数据的集合,是一个容器,用于存储多个数据。 2.数组的优点数组中的每个元素都有下表值,下标从0开始。下标值方便程序员对数组中的数据进行操作。 3.数组定义的格式1)元素类型[]数组名=new 元素类型[元素个数或数组长度]; 这种定义方法称之为动态定义法。 示例:int[] arr = new int[5]; 2) 元素类型[]数组名= new 元素类型[]{元素,元素,……}; 这种定义方法称之为静态定义法。 示例:int[] arr = new int[] {3,5,1,7}; int[] arr = {3,5,1,7}; 二、引用数据类型内存结构 1.Java内存结构由于Java对不同类型的数据有不同的处理方式,所以Java对内存进行了不同的区域划分。这提高了运算效率,优化了内存管理方式。 1)栈内存栈内存用于储存局部变量。当数据使用完毕之后,其所占空间会自动释放。 2)堆内存a. 堆内存用于储存对象和数组,所有通过new建立的实例都在堆内存中存放;b. 每一个对象实例都有一个内存地址;c. 实例中的变量都有默认的初始化值;d. 实例不再被使用时(没有任何引用指向该实例),该实例会在不确定的时间被垃圾回收器回收,释放内存 2.数组的内存结构示意图数组属于引用数据类型,其内存结构示意图如下: 当执行int[] x = new int[3]时,1)在栈内存开辟一个内存空间,用于存储变量x;2)在堆内存开辟内存空间,用于存储new出来的数组对象实例;3)将数组对象的内存首地址(0x0079)赋给x;4)至此,x就是数组对象的引用,指向数组对象 3.两个引用指向同一数组对象实例 该代码段中,将数组的内存地址引用赋给了x,也赋给了y。那么x,y就指向了同一数组对象。x,y的内存情况如下图: 因此,当x = null执行之后,内存中并没有产生垃圾,因为变量y也指向该数组,该数组仍处于被引用状态。同时,y[1] = 89执行之后,x[1]的值也将变为89,而不是0。 4.基本数据类型内存结构对比引用数据类型中,两个变量指向同一对象实例,其中一个变量对对象的值进行修改,会影响另一个变量,这是引用数据类型的规律。下面对比一下基本数据类型做同样的赋值操作之后的内存示意图。 运行结束后,a的值仍旧为5。内存图如下: 三、数组操作过程中常见的异常 1.ArrayIndexOutOfBoundsException数组下标越界异常 arr[3]超出下标范围,出现异常。 2.NullPointerException空指针异常 arr被赋值为空,已经无法指向数组对象,再使用arr操作数组,出现空指针异常。 四、排序算法 1.选择排序1)从下标为0的数开始,逐一和后面的数进行比较,遇到小的数,则交换位置…
Java基础—for循环的嵌套
利用for循环的嵌套打印六种类型的 * 形三角。示例一: 示例二: 示例三: 示例四: 示例五: 示例六: 写代码之前,最重要的是先有思路,然后写出步骤,分阶段完成各个目标,达到最终结果。