Java程序设计基础之面向对象(下)
(补充了上的一些遗漏的知识,同时加入了自己的笔记的ヾ(•ω•`)o)
(至于为什么分P,啊大概是为了自己查笔记方便(?)应该是(〃` 3′〃))
(但是u1s1,学完了面向对象后反而更懵逼,下一步先刷算法吧,然后Java的学习也跟上,今年争取考完二级证书(o-ωq)).oO 困)
目录
一、面向对象
(一)快捷键
(二)继承
(三)封装
(四)多态
(五)Object类
(六)关键字
(七)操作符
(八)抽象类
(九)接口
(十)内部类
一、面向对象
(一)快捷键
1.Eclipse:
(1)setter and getter 右键 + Source
2.Idea:
(1)setter and getter Alt + Insert
(二)继承
1.概念:继承是面向对象语言的重要机制。借助继承,可以扩展原有的代码,应用到其他程序中,而不必重新编写这些代码。在java语言中,继承是通过扩展原有的类,声明新类来实现的。扩展声明的新类称为子类,原有的类称为超类(父类)。继承机制规定,子类可以拥有超类的所有属性和方法,也可以扩展定义自己特有的属性,增加新方法和重新定义超类的方法。(来自百度百科)
2.在Java中,继承是一种主要思想。通过父子类的继承、抽象类的继承、接口的继承……可以通过继承来完成调用。
3.继承的方法:
(1)父子类:在面向对象(上)中,已经描述了继承的方法,通过关键字extends完成父子类的继承;
(2)接口:接口是特殊的抽象类,我们能够通过抽象类来调用方法,通过此方法调用后,只需要重写接口的内容就可以调用;
(三)封装
1.Java的封装,就是把一些非公开的块进行封装,不让使用者/调用者进行查看,常见的形式是通过修饰词的使用,如private来进行封装;
2.包装类(Wrapper)
(1)针对八种基本定义相应的引用类型——包装类(封装类)
(2)装箱与拆箱
a.基本数据类型包装成包装类:装箱
//通过包装类的构造器实现 int i = 500; Integer t = new Integer(i);
//通过字符串参数构造包装类对象 Float f = new Float("4.56"); Long l = new Long("abcd");
b.获得包装类对象中包装的基本类型变量:拆箱
//调用包装类的 .xxxValue();方法 Integer i = new Integer(112); int i0 = i.intValue(); boolean b = new Boolean(false).booleanValue();
c.自动装箱
//等同于上文中的Integer i = new Integer(112); Integer il = 112;
d.自动拆箱
//自动拆箱Integer il = 112; int i2 = i1; //等同于boolean b = new Boolean(false).booleanValue(); boolean b = new Boolean(false);
e.将字符串转换成基本数据类型
//通过包装类的构造器实现 int i = new Integer("123");
//通过包装类的parseXxx(String s)静态方法 int i = Integer.parseInt("123"); float f = Float.parseFloat("0.123"); boolean b = Boolean.parseBoolean("false");
f.将基本数据类型转换成字符串
//以上文中的i f b做示例 String istr = String.valueOf(i); String fstr = String.valueOf(f); String bstr = String.valueOf(ture);
(四)多态
1.多态性,是面向对象中最重要的概念,在Java中有两种体现:
(1)方法的重载与重写(Overload and Override);
(2)对象的多态性:可以直接应用在抽象类和接口上;
2.方法的重写:在子类中可以根据需要对从父类中继承来的方法进行改造,也称方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
注意事项 :
△ 重写方法必须和被重写方法具有相同的方法名称、参数列表和返回值类型;
△ 重写方法不能使用比被重写方法更严格的访问权限;
△ 重写和被重写的方法须同时为static的,或同时为非static的子类方法抛出的异常不能大于父类被重写方法的异常;
3.子类可看做是特殊的父类,所以父类类型的引用可以指向子类的对象:即,向上转型(upcasting);
4.一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能再访问子类中添加的属性和方法
Student m = new Student(); m.school = “pku”; //合法,Student类有school成员变量 Person e = new Student(); e.school = “pku”; //非法,Person类没有school成员变量。 属性是在编译时确定的,编译时e为Person类型,没有school成员变量,因而编译错误。
5.虚拟方法调用(Virtual Method Invocation)
//正常的方法调用 Person p = new Person(); p.getInfo(); Student s = new Student(); s.getInfo(); //虚拟方法调用(多态情况下) Person e = new Student(); e.getInfo(); //调用Student类的getInfo()方法
# 编译时类型和运行时类型编译时e为Person类型,而方法的调用是在运行时确定的,所以调用的是Student类的getInfo()方法。——动态绑定
# 当调用成员变量时,因为成员变量不具备多态性,所以引用时,我们只考虑引用变量所属类中是否有我们的属性;
# 而当调用成员方法时,我们在编译时,要查看引用变量所属的类中是否有所调用的方法,所有需要我们的父子类中都存在方法体,但是当我们运行时,只考虑调用的实际对象所属的类中的重写方法;
6.多态小结
(1)成员方法:
编译时:要查看引用变量所属的类中是否有所调用的方法。
运行时:调用实际对象所属的类中的重写方法。
(2)成员变量:不具备多态性,只看引用变量所属的类。
(五)Object类
1.Object类是所有Java类的根父类;
2.Object类的主要方法:
(1)public Object() # 构造方法
(2)public boolean equals(Object obj) # 对象比较
(3)public int hashCode() # 取得Hash码
(4)public String toString() # 取得地址
3.对象类型转换(Casting)
(1)基本类型数据转换:小的数据类型可以自动转换成大的数据类型;
强制类型转换:大的数据类型转换到小的数据类型则需要进行强转,表示方法为:long a = (long) b; float x = (float) y;
(2)Java对象的强制类型转化(造型)
在下图的代码中,Person类中是没有方法体getschool的,所以此时我们需要调用方法时,需要将Person e强转为Student,此时就可以调用方法getschool;
public class Test{ public void method(Person e) { //设Person类中没有getschool()方法 // System.out.pritnln(e.getschool()); //非法,编译时错误 if(e instanceof Student){ Student me = (Student)e; //将e强制转换为Student类型 System.out.pritnln(me.getschool()); } } public static void main(Stirng args[]){ Test t = new Test(); Student m = new Student(); t.method(m); } }
(六)关键字
1.this 关键字
(1)使用this关键字:在一个实例方法或一个构造器中,关键字this是对当前对象的引用。所谓当前对象,指的是其方法或构造器正在被调用的对象,也就是正在调用的方法或构造器所在的对象。可以通过this在一个实例方法或构造器中引用当前对象的任何成员。
(2)最经常使用this关键字的情况,是在对象的一个字段被方法或构造器的参数屏蔽时,需要调用这个被屏蔽的字段的这种情况。
(3)对构造器使用this:在一个构造器中,还可以使用this关键字来调用同一个类中的另外的构造器,这种做法称为“显式构造器调用”。
//this在方法内部使用,即这个方法所属对象的印象 //this在构造器内部使用,表示该构造器正在初始化的对象 // @this表示当前对象,可以调用类的属性、方法和构造器 public class Person { //构造体中this的调用 public Person(){} //① public Person(int age){ //② this.age = age; } public Person(String name){ //③ this(); //此句则表示进行了①的调用 this.name = name; } public Person(int age,String name){ this(1); //进行了②的调用
//Attention!!this进行构造体的调用时,要写在方法的第一句 //this表示的是构造器中初始化的age,而后面的age表示的是形参的age this.age = age; this.name = name; } int age; String name; public void setName(String name){ //this表示的是方法中这个方法所属对象的印象,而后面的name表示的是形参的name this.name = name; } public void setName01(String name) { //this表示调用的是setName方法,而后面的name表示的是形参的name this.setName(name); } public void showInfo(){ System.out.println("姓名:" + this.name); System.out.println("年龄:" + this.age); } }
2.super 关键字
(1)在Java类中使用super来调用父类中的指定操作:
(2)super可用于访问父类中定义的属性
(3)super可用于调用父类中定义的成员方法
(4)super可用于在子类构造方法中调用父类的构造器
注意事项:
△ 尤其当子父类出现同名成员时,可以用super进行区分
△ super的追溯不仅限于直接父类
△ super和this的用法相像,this代表本类对象的引用,super代表父类的内存空间的标识
3.this与super的区别
4.static关键字
(1)在Java中,static可以用来修饰属性、方法、代码块、内部类;
(2)类变量(class Variable):被static所修饰的变量就是类变量,他是静态的,如果不想变量被改变,那么就可以使用静态变量;
类变量(类属性)由该类的所有实例共享;类变量不需要通过实例化就可以进行使用;
(3)类方法(class Method):被static所修饰的方法就是类方法;
没有对象的实例时,可以用 类名.方法名() 的形式访问由static标记的类方法;同时,在类方法中只能访问类的static属性;
因为不需要实例化就能访问,所以类方法中不能有 this 和 super 关键字;
(4)代码块中,优先执行静态代码块,其次是代码块,然后才是其他方法;
5.final关键字
(1)在Java中,final关键字用来表示“最终”的意思;
(2)final标记的类不能被继承;
(3)final标记的方法不能被子类重写;
(4)我们称final修饰的变量为常量,只能被赋值一次,名称大写;
(七)操作符
1.instanceof操作符
x instanceof A:检验x是否为类A的对象,返回值为boolean型。要求x所属的类与类A必须是子类和父类的关系,否则编译错误。如果x属于类A的子类B,x instanceof A值也为true。
public class Person extends Object {…} public class Student extends Person {…} public class Graduate extends Person {…} public void method1(Person e) { if (e instanceof Person) //处理Person类及其子类对象 if (e instanceof Student) //处理Student类及其子类对象 if (e instanceof Graduate) //处理Graduate类及其子类对象 }
# 要求x所属的类与类A必须是子类和父类的关系,否则编译错误;
# 如果x属于类A的子类B,x instanceof A值也为true;
2. 【==】操作符 && equals操作符
(1)【==】操作符基本类型比较:只要两个变量的值相等,即为ture;
引用类型比较引用(是否指向同一个对象):只有指向同一个对象时,才返回ture;
用【==】进行比较时,符号两边的数据类型必须兼容(可自动转换的基本类型除外),否则编译出错;
(2)equals():所有类都继承了Object,也就获得了equals()方法,还可以重写;
只能比较引用类型,其对象与【==】相同,比较是否指向同一个对象;
特例:使用equals对File、String、Data及包装类来说,是比较类型及内容而不考虑引用的是否是同一个对象;
原因:在这些类中重写了Object类的equals方法。
(八)抽象类
1.用abstract关键字来修饰一个类时,这个类叫做抽象类;用abstract来修饰一个方法时,该方法叫做抽象方法;
2.抽象方法:只有方法的声明,没有方法的实现;以分号结束:abstract int abstractMethod(int a);
3.含有抽象方法的类必须被声明为抽象类
4.抽象类不能被实例化。抽象类是用来作为父类被继承的,抽象类的子类必须重写父类的抽象方法,并提供方法体。若没有重写全部的抽象方法,仍为抽象类;
5.不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法;
(九)接口(interfac)
1.接口是特殊的抽象类;
2.在我们进行父子类的调用时,因为Java不支持多重继承,所以我们可以通过接口进行多重的继承,只需要重写方法体即可;
3.实现接口:class 类名 implements 接口名{ }
4.一个类可以实现多个接口,通过“ ,”进行多个接口的串联;接口也可以继承其他接口;
5.接口的特点:用interface来定义;
接口中的所有成员变量都默认是由public static final修饰的;
接口中的所有方法都默认是由public abstract修饰的;
接口没有构造器;
接口采用多层继承机制。
6.实现接口的类中必须提供接口中所有方法的具体实现内容,方可实例化;否则,仍为抽象类;
接口的主要用途就是被实现类实现(面向接口编程);
与继承关系类似,接口与实现类之间存在多态性;
定义Java类的语法格式:先写extends,后写implements;
(十)内部类(Inner class)
1.在类中写的类就是内部类;
2.匿名内部类:不能定义任何静态成员、方法和类,只能创建匿名内部类的一个实例;一个匿名内部类一定是在new的后面,用其隐含实现一个接口或实现一个类;
3.内部类的作用:解决Java中不能多重继承的问题;通过内部类继承来继承多个类进行重写;
4.内部类的使用方法;
public class Test{ int i; public int z; private int k; //内部类 A class A{ public void setTestFileds(){ //在Test类中的成员变量,所以不能直接通过this调用,而是Test.this Test.this.i = 1; Test.this.z = 2; Test.this.k = 3; } } //调用类A public void setInfo(){ new A().setTestFileds(); } //输出类A public void showInfo(){ System.out.println(this.i); System.out.println(this.z); System.out.println(this.k); } }