第四章:面向对象(下)
面向对象的的特点之一:能够使用以前建造的类的方法和属性
4.1 类的继承
继承的特点
public class Person{
public String name;
public int age;
public Person(String name,int age){
this.name=name;
this.age=age;
}
public Person(){
}
public void getInfo(){
System.out.println(name);
System.out.println(age);
}
}
public class Student extends Person{
public String study(){
System.out.println("Studding");
}
public static void main(String[] agrs){
Person p=new Person();
p.name="Person";
p.age=30;
p.getInfo();
Student s=new Student();
s.name="student";
s.age=16;
s.getInfo();
s.study();
}
}
java中只支持单继承,不允许多继承。但是一个类可以被多个类继承
子类继承父类的所有的所有成员变量和成员方法,淡不继承父类的构造方法,在子类的构造方法中用super()
调用父类构造方法。
如:class Student extends Person{
public Student(String name,int age,String school){
super(name,age);
this.school=school;
}
}
如果没有显示的定义构造函数,系统为会其默认赋予无参构造函数。
一般类说定义了一个有参的构造函数,随便添加一个无参的构造函数
子类对象的实例化过程
略。。。
覆盖父类的方法
子类中可以根据对父类中继承来的方法记性改造,->方法覆盖(重写)
重写->继承关系,方法的签名相同(名称,参数列表,返回值类型)
public class Person{
public String name;
public int age;
public void getInfo(){//只是提供输出name和age的语句
System.out.println("name="+name);
System.out.println("age="+age);
}
}
class Student extends Person{//这个类继承了Person
public String school;
public void study(){
System.out.println("Studying.....");
}
public void getInfo(){//重写的这个方法的权限不能低于父类的权限
super.getInfo();//调用父类被覆盖的方法 super.方法名()
System.out.println("School="+school);//增添想要输出的学校
}
public static void main(String[] agrs){
Person p=new Person();
p.age=30;
p.name="z1";
p.getInfo();
Student s=new Student();
s.name="xs";
s.age=21;
s.school="hngxy";
s.getInfo();
s.study();
}
}
final关键字
1、在java中声明类、属性、方法时,可以使用关键字final来修饰
2、final标记的类不能被继承
3、final标记的方法不能被子类重写
4、final标记的变量即成为常量,只能赋值一次
final标记的成员变量必须在声明的同时或在该类的构造方法中西那是赋值,才能被使用
4.2 抽象类与接口
抽象类 -> abstract
JAVA中可以定义一些不含方法体的方法,方法的实现交由子类实现,这样的方法叫做抽象方法,这个样的类叫做抽象类
定义规则:
抽象类不能被实例化(不能用new去产生对象)
抽象方法只是需要什么,不需要实现
含有抽象方法的类必须被声明为抽象类,抽象类的子类需要实现所有的抽象方法,否则仍然是抽象类
抽象方法的写法:
abstract 返回值类型 抽象方法(参数列表);
示例:
abstract class A{
abstract int aa(int x,int y); //记得是这样写的
//下面这样写是错的,后面那样是叫做空是实现,而不是没有实现
// abstract int aa(int x,int y){}
}
注意: 含有抽象方法的类一定是抽象类,但是抽象类中的方法不一定全是抽象的
接口 interface (抽象方法和常量的集合-> 特殊的抽象类)
若如果抽象类的的所有的方法都是抽象的,就可以将这个类用另外的方式来定义也就是接口
示例:
//所有的成员都是public修饰的
public interface Runner{
int ID=1; //这里是public static final -> 全局静态常量
void run();
}
////////////////////////////////////
interface Animal extends Runner{//接口可以继承一个接口 -> extends
void breath();
}
class Fish implements Animal{//子类实现接口 -> implements
public void run(){
System.out.println("fish is swing");
}
public void breathe(){
System.out.println("fish is bubbling");
}
}
abstract LandAnimal implements Animal{ //抽象类实现接口
public void breath(){
System.out.println("LandAnimal is breathing");
}
}
//设计接口的目的就是为了让类不被java的单一继承限制,一个父亲,多个干爸
C++中多重继承的复杂性在于一个有可能继承同一个方法的不同实现,而对于实施抽象的方法的接口这种可能性是没有的
注意:一个类可以继承一个父类的同时,实现多个接口,extends 关键字需要房子啊implements前面
如:class Student extends Person implements Runner,Flyer{...}
总结:实现一个接口就是要实现该接口的的所有方法
接口中的方法都是抽象的
多个无关的类可以实现同一个接口,一个类可以实现多个无关的接口
4.3 对象的多态性
对象类型的转换
public class Pencil {
private String content;
public void write(){
System.out.println("content: "+content);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Pencil(String content) {
super();
this.content = content;
}
public Pencil() {
super();
}
}
public class RubberPencil extends Pencil{
public RubberPencil() {
super();
}
public RubberPencil(String content) {
super(content);
}
public void write(){//重写!!
System.out.println("content which is write is : "+this.getContent());
}
public void erase(){
System.out.println("content which is erase is :"+this.getContent());
}
public static void main(String[] agrs){
//RubberPencil rp=new RubberPencil("1234");
//Pencil p=rp; -> 子类能够自动转换成父类的类型
//下面的这一行等价于上面的2行 是父类引用指向子类对象 可以把一个带橡皮擦的铅笔当做铅笔来用
Pencil p=new RubberPencil("1234");
p.write(); //->new 哪个调用的就是那个的write()
//这里的P虽然实质上是RubberPencil,不能把一个铅笔当做有橡皮擦的铅笔,但是他得引用只是Pencil 这里也是一个有限的地方
//必须要把 P 强制类型转换成 RubberPencil 才能调用子类中独有的erase()
//类型转换 (目标类型)源类型
((RubberPencil)p).erase();
}
}
instanceof 操作符
->用于判断一个类是否是实现了某个接口,也用于判断一个实例对象是否属于一个类
对象 instanceof 类(接口)
Object 类(最高层类,所以类的超类)
->比较特殊的类,它是所有类的父类 所有的类默认继承了Object,Object的方法适用于所有的类
public class Person{...} -> == -> public class Person extends Object{...}
面向对象的多态性
同一段程序代码却又不同的结果,这就是面向对象的多态性。
->应用程序不必为每一个派生类(子类)编写功能调用,只需要对抽象的基类进行处理
->派生类的功能可以被基类的方法或引用变量调用,向后兼容
匿名内部类
下回分解....
4.4 异常->定义了程序中晕倒的非致命的错误,而不是编译时的语法错误。
try ... catch 语句
public class TestException{
public static void main(String[] agrs){
try{//try这个代码块出现错误,会转到catch那个代码块中去执行的
int result=new Test().devide(3,0);
System.out.println("the result is "+result);
}catch(Exception e){//系统将异常的情况封装到对象
System.out.println(e.getMessage());
}
System.out.println("the result is "+result);
}
}
class Test{//出现异常的情况就是除数=0了
public int devide(int x,int y){
int result=x/y;
return x/y;
}
}
throws 关键字
对于有可能发生异常的方法,用throws关键字声明下,调用者在调用该方法时就必须用try..catch语句处理,或是在主函数那进行抛出
throws Exception否则无法通过编译。
class Test{//出现异常的情况就是除数=0了
public int devide(int x,int y) throws Exception{
int result=x/y;
return x/y;
}
}
自定义异常与throws关键字
4.5 包 -> 通过引入包的机制,提供类的多层类命名空间,解决命名冲突和管理问题
如:
package com.cx;
public class T1{
public static void main(String[] agrs){
System.out.println();
}
}
若是按照常规那样的javac 产生的字节码文件还是在相同的目录下,但是此时要想java 这个字节码就会出现
问题了,这个字节码文件在文件系统中(硬盘)必须有与包名相对应的目录结构
现在我把这个T1.java放置在了E盘的根目录下,根据我的想象,就是说运行javac T1.java 就会产生相应
的目录结构用于存放 T1.class 但是这样运行的结果还是T1.class 和 T1.java 是在同个目录下,没有任何
变化,对此我确实比较郁闷啊。
其实真正能够产生这样的目录结构的是 javac -d . T1.java
这样就产生了 com.xh 的这个目录并且T1.class 也被放置到这下面去了。
运行的时候就是 java com.xh.T2 -> OK
import 语句及应用
这个就不说了,如果不加上不导入包名的话,从头到尾将使用的类全部打出来,那不得累死啊
4.6 访问控制
类成员的访问控制
private —> 同个类中调用
____默认 -> 被同一个包的所有的类调用(包类型)
protected -> 只要是经过继承的,不管是否在同一个包下,都能调用
public -> 所有的类都能够访问
private 是私有的-> 默认 包访问 -> protected 包+子类 -> public 所有
类的访问控制
类同样也是有访问控制符的,但是类本身只有两个访问控制符,即是public 和默认。
若是被修饰为private和protected,那么这个类将不可以被继承。
Java的命名习惯
->
包名 所有的字母一律小写
类名、接口名 首字母要大写
方法名 首字母小写,后边的单词首字母大写
变量名 首字母小写,后边的单词首字母大写
常量名 每个字母一律大写
4.7 使用jar文件 -> JAVA Archive File (java 档案文件) -> 压缩文件
使用WinRAR 对jar文件进行查看
-> 这个还没怎么用过,不写了。。再说了!!