面向对象编程(一):
包
(1)导入包中的类
== 包是组织类的一种方式,使用包就是为了保证类的唯一性== 就比如你和另外一个人都写了一个Test的类,如果出现两个同名的类, 就会冲突, 导致代码不能编译通过,但是如果你们两个在不同的包里面那就不会造成冲突了!
可以使用 java.util.Date 这种方式引入 java.util 这个包中的 Date 类,但是这种写法比较麻烦一些, 可以使用 import 语句导入包。
*如果需要使用 java.util 中的其他类, 可以使用 import java.util. , 但是建议显式的指定要导入的类名. 否则还是容易出现冲突的情况。 如下图如果我们都使用== * == java.sql 中的类 java.sql.Date 和 java.util 中的类 java.util.Date 都匹配,这个时候系统就会报错。
注意事项: import 和 C++ 的 #include 差别很大. C++ 必须 #include 来引入其他文件内容, 但是 Java 不需要.
import 只是为了写代码的时候更方便. import 更类似于 C++ 的 namespace 和 using
(2)静态导入
我们可以使用 import static 可以导入包中的静态的方法和字段,这种方法可以更方便的写一些代码,但是本人觉得这样代码的可读性会降低。
(3)将类放到包中
基本规则 :
在文件的最上方加上一个 package 语句指定该代码在哪个包中. 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1).
包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存 储代码. 如果一个类没有 package 语句, 则该类被放到一个默认包中.
(4)包的访问权限控制
类中的 public 和 private. private 中的成员只能被类的内部使用. 如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.
这两个类在同一个包中所以可以进行调用。
使用不在同一个包内的Test类进行调用:
不在一个包内的类调用程序会报错
(5)常见的系统包
1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。
2. java.lang.reflect:java 反射编程包;
3. java.net:进行网络编程开发包。
4. java.sql:进行数据库开发的支持包。
5. java.util:是java提供的工具程序包。(集合类等)
6. java.io:I/O编程开发包。
继承
代码中创建的类, 主要是为了抽象现实中的一些事物(包含属性和方法).
有的时候客观事物之间就存在一些关联关系, 那么在表示成类和对象的时候也会存在一定的关联.
构造子类的时候必须要先构造父类
例如, 设计一个类表示动物,动物是父类,狗为子类
public class Animals {
public String name;
public Animals (String name){
this.name = name;
}
public void eat(String food){
System.out.println(this.name+"吃"+food);
}
}
class Dog extends Animals {
public Dog(String name) {
//构造父类
super(name);
}
}
extends关键字
extends 指定父类.(基类、超类)
1、Java 中一个子类(派生类)只能继承一个父类 (而C++/Python等语言支持多继承)。
2、子类会继承父类除构造函数以外所有的东西
3、对于父类的 private 的字段和方法, 子类中是无法访问的,但是可以使用super关键字得到父类的字段。
4、子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用,也就是说子类要实例化必须先实例化父类,就是用子类的构造函数必须先调用父类的构造函数使用super关键字。
super关键字(父类对象的引用)
1、super() 表示调用父类的构造函数 只能调用一次,放在子类的第一行,其中的参数可变
2、super.data 表示调用父类的属性
3、super.func()表示调用父类的方法
注:子类并没有继承父类的构造方法,只是在子类中进行了显示的调用
this关键字
对当前对象的引用
1、this():调用其他的构造方法
2、this.data 调用属性
3、this.func()调用方法
protected 关键字
如果把字段设为 private, 子类不能访问. 但是设成 public, 又违背了我们 “封装” 的初衷.
那两全其美的办法就是 protected 关键字.
可访问范围:
== 同一个包中的同一个类
同一个包中的不同类
不同包中的子类(需要使用super关键字)==
不同包中的非子类是不能访问的!!!
default
默认访问权限(也叫包访问权限):只能在一个包中进行访问
Java 中对于字段和方法共有四种访问权限:
private: 类内部能访问, 类外部不能访问
默认(也叫包访问权限): 类内部能访问, 同一个包中的类可以访问, 其他类不能访问.
protected: 类内部能访问, 子类和同一个包中的类可以访问, 其他类不能访问.
public : 类内部和类的调用者都能访问
final关键字
final 修饰变量就变成常量
final 修饰方法就变成密封方法
final 关键字的功能是限制类被继承,在一个类前面加上final就不能被继承成为密封类。
组合
和继承类似, 组合也是一种表达类之间关系的方式, 也是能够达到代码重用的效果
public class Student {
...
}
public class Teacher {
...
}
public class School {
public Student[] students;
public Teacher[] teachers;
}
组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段.
组合表示 ==has - a或者 a part of 一部分 == 语义
在刚才的例子中, 我们可以理解成一个学校中 “包含” 若干学生和教师.
继承表示 is - a语义
在上面的 “动物和狗” 的例子中, 我们可以理解成一只狗也 “是” 一种动物.
多态(动态绑定)
构造函数中可以发生运行绑定(动态绑定)
对子类实例化后运行时先执行父类的成员方法,父类和子类都重写后引用了子类的方法。
动态绑定
java反编译命令: javap-c
运行时绑定,(编译时调用的是父类方法)
1、发生向上转型
2、子类和父类有同名的覆盖方法
3、通过父类的引用,调用该重写方法,此时会发生动态绑定
向上转型
子类对象赋值给父类(父类引用了子类对象)
向上转型的过程中:
通过父类引用,只能引用父类自己的方法或者属性。
向上转型的三种情况
1、直接赋值
2、传参
3、返回值
向下转型
不安全
要发生向下转型必须先 发生同种类型的向上转型,
如果在Cat类当中没有fiy方法我们使用强转会发生错误因为这里 animal 本质上引用的是一个 Cat 对象, 是不能转成 Bird 对象的. 运行时就会抛出异常。
Animal animal = new Cat("小猫");
Bird bird = (Bird)animal;
bird.fly();
// 执行结果, 抛出异常
Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to Bird
at Test.main(Test.java:35)
instanceof 可以判定一个引用是否是某个类的实例. 如果是, 则返回 true. 这时再进行向下转型就比较安全了
Animal animal = new Cat("小猫");
if (animal instanceof Bird) {
Bird bird = (Bird)animal;
bird.fly();
}
重写(覆盖):
1、方法名相同
2、参数列表相同(参数个数、类型)
3、返回值相同(返回值可以不同,但是要遵循协变类型—》返回值之间可以构成继承关系)
4、一般发生在继承关系上
注:
1、需要重写的方法的访问修饰限定符不能是privatre
2、访问修饰限定符不一定需要相同的,只要满足子类的访问修饰限定符区间要大于等于父类的访问修饰限定符区间
3、静态的方法不能被重写
重载:
1、方法名相同
2、参数列表不同(参数个数、类型)
3、返回值不做要求