1.包
包是组织类的一种方式。
使用包的主要目的是保证类的唯一性。
如:在代码同个包低下写了两个名称相同的类,就会冲突,导致代码不能编译通过。
使用 import 可以导入我们所需要的包
import java.util.date;
import java.util.* //表示导入Java.util包底下所有的方法/类
public class test{
public static void main(String[] args){
Date date = new Date();
system.out.println(date.getTime());
}
}
静态导入,使用import可以导入包中所有的静态方法和字段,
如:import static java.lang.Math.*
包的访问权限控制
范围 | 同一包中的同一类 | 同一包中的不同类 | 不同包中的子类 | 不同包中的非子类 |
---|---|---|---|---|
defaul | ok | ok | ||
private | ok | |||
protected | ok | ok | ok | |
public | ok | ok | ok | ok |
2.继承
代码中创建的类,主要是为了抽象现实中的一些事物(包含属性和方法)
有的时候客观事物之间存在一些关联关系,那么在表示程类和对象的时候也会存在一定的关联
代码示例
class Animal{
public String name;
public Animal(){
}
public Animal(String name){
this.name = name;
}
public void eat(String food){
System.out.println(this.name+"在吃"+food);
}
}
class Cat{
public String name;
public Cat(){
}
public Cat(String name){
this.name =name;
}
public void eat(String food){
System.out.println(this.name+"正在吃"+food);
}
}
public class test {
public static void main(String[] args){
Animal a =new Animal();
Cat Tom = new Cat();
a.eat("meat");
Tom.eat("Jerry");
}
}
很明显在Annimal类和Cat之间出现大量冗余,两者之间存在着大量相同的定义,下面用继承的方式来定义相同的类,从逻辑上来说Cat属于Animal的子类,因此可以让Cat继承Animal类达到代码重用的效果,此时Animal这样被继承的类,称为父类或超类、基类,至于Cat这样的称为子类,派生类,
class Animal{
public String name;
public Animal(){
}
public Animal(String name){
this.name = name;
}
public void eat(String food){
System.out.println(this.name+"在吃"+food);
}
}
class Cat extends Animal{
public Cat(String name){
super(name);//调用父类Animal的构造方法
}
}
public class test {
public static void main(String[] args){
Animal a =new Animal();
Cat Tom = new Cat("Tom");
a.eat("meat");
Tom.eat("Jerry");
}
}
继承的语法规则:
使用extends指定要继承的父类,
一个子类只能继承一个父类
子类能够继承父类所有内容
对于父类中的private字段和方法,子类是无法访问的
子类的实例中,也包含着父类的实例,可以使用super关键字得到父类实例的引用
子类构造的时候,需要首先帮助父类进行构造,在子类的构造方法内部,调用父类的构造方法,
super//显示调用父类的构造方法,
个人理解:通过继承父类,子类能够获得父类所有的属性,子类通过构建父类,引用父类,达到继承父类的作用
子类等同于对父类的扩展,首先通过父类实例化一个对象,然后在这个对象的基础上去添加独立属性和方法
protected的使用
protected关键字
对于类的调用者来说;protected修饰的字段和方法是不能访问的,
对于类的子类和同一个包底下的其他类来说,protected修饰的字段和方法是可以访问的
protected保证了类中的属性不被调用者使用且能够被子类继承
class Animal{
protected String name;
public Animal(){
}
public Animal(String name){
this.name = name;
}
public void eat(String food){
System.out.println(this.name+"在吃"+food);
}
}
class Cat extends Animal{
public Cat(String name){
super(name);
}
}
由于类之间能够不断的被继承,当我们不想当前定义的类被别的类继承时
需要利用final 关键字
final的功能时限制类被继承
用final修饰的类被继承的时候,就会编译出错
3.向上转型和动态绑定
public class upward {
public static void main(String[] args) {
Animal animal=new Animal("小动物");
Animal animal2 = new Dog("tom");//向上转型,父类指向子类,将DOG引用为animal,
animal.eat();
animal2.eat();
//可以看出虽然向上转型实现了父类指向子类,但在调用eat方法时仍旧指向了子类的方法
//对于这种情况称为动态绑定
}
}
class Animal{
public String name;
public int age;
public void eat(){
System.out.println(this.name+"吃食物");
}
public Animal(String name) {
this.name = name;
}
}
class Dog extends Animal{
public Dog(String name) {
super(name);
}
public void eat(){
System.out.println(super.name+"吃狗粮");
}
}
此时的animal2表示一个父类的引用,但其指向了Dog子类,此种写法称为向上转型,
也就是说,animal2表示狗,但其本质是动物,所以引用的所有内容皆来自Dog类中与Animal相同的内容
向上转型发生的条件:
1、直接将子类赋值给父类引用
2、将子类作为参数传给父类
3、方法返回指定为父类,但实际返回了子类
当子类和父类定义了同名方法时且参数列表相同,返回值相同时
会发生动态绑定
可以发现animal2调用了Dog中的eat方法,animal调用了父类本身的方法,
因此java中调用某个类的方法时,究竟执行了哪段代码,要看当前引用指向父类对象还是子类对象,这个过程是程序运行时决定的,
因此称为动态绑定
4.方法重写
关于上述动态绑定中出现的情况称为重写
子类实现了父类的同名方法,且参数的类型和个数完全相同,
注意事项:
1.重写和重载完全不一样,
2.普通方法可以重写,但static修饰的静态方法不能重写
3.重写时子类方法的访问权限不能低于父类方法的访问权限
4.重写的方法返回值类型不一定和父类的方法相同
重写和重载的区别:
区别 | 重载overload | override |
---|---|---|
概念 | 方法名称相同,参数的类型及个数不同 | 方法名称、返回值类型、参数类型及个数完全相同 |
范围 | 一个类 | 继承关系 |
限制 | 没有权限要求 | 被覆写的方法不能拥有比父类更严格的访问权限 |