包:
包 (package) 是组织类的一种方式.
使用包的主要目的是保证类的唯一性.
将类放到包中
- 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.baidu.demo1 ).
- 包名要和代码路径相匹配. 例如创建 com.bit.demo1 的包, 那么会存在一个对应的路径 com/bit/demo1 来存储代码.
- 如果一个类没有 package 语句, 则该类被放到一个默认包中.
导入包中的类
Java 中已经提供了很多现成的类供我们使用
如import java.util.Data;
import java.util.*;//导入util包中所有的类
import java.util.Date;
//import java.util.*
public class Test {
public static void main(String[] args) {
Date date = new Date();
// 得到一个毫秒级别的时间戳
System.out.println(date.getTime());
}
}
导入静态包使代码更方便
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
double x = 30;
double y = 40;
// 静态导入的方式写起来更方便一些.
// double result = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
double result = sqrt(pow(x, 2) + pow(y, 2));
System.out.println(result);
}
}
继承:
- java是单继承语言
- 在子类中, 只写独有的属性或方法 不用写父类中已有的
- 若父类中定义了String name ,则在子类的构造方法中:
使用 super(name); //显示调用父类的构造方法
如代码:
class Animal {
public String name;
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 调用父类的构造方法.
super(name);
}
}
protected
如果父类属性访问权限设为private 则子类不能访问
故最好用 protected 既体现封装性,子类也可以访问
final
final int a = 10; // 被final修饰为常量
final class A {} //被final修饰的类叫 密封类 即这个类不能被继承
范围 | private | default | protected | public |
---|---|---|---|---|
同一包中的同一类 | √ | √ | √ | √ |
同一包中的不同类 | √ | √ | √ | |
不同包中的子类 | √ | √ | ||
不同包中的非子类 | √ |
多态:
父类引用 引用子类的对象 —》叫向上转型
向上转型:(发生的三个时机)
1.赋值子类给父类
Bird bird = new Bird("圆圆");
Animal bird2 = bird;
// 或者写成下面的方式
Animal bird2 = new Bird("圆圆");
注意: 此时bird2只能调用父类自己的方法或者访问自己属性
如果想调用Bird类中的方法,则需要向下转型
2.方法传参
public class Test {
public static void main(String[] args) {
Bird bird = new Bird("圆圆");
feed(bird);
}
public static void feed(Animal animal) {
animal.eat("谷子");
}
}
3.方法返回
public class Test {
public static void main(String[] args) {
Animal animal = findMyAnimal();
}
public static Animal findMyAnimal() {
Bird bird = new Bird("圆圆");
return bird;
}
}
向下转型:
前提条件:父类已经引用了子类对象,且子类要为向下转型的类型
若想让bird2调用Bird类中的方法,则需要向下转型{
// (Bird) 表示强制类型转换
Bird bird = (Bird)bird2; //向下转型
bird.fly();
如果 new 一个实例
Bird bird = new Bird("圆圆");
则调用顺序如下:
父类静态 子类静态 父类实例 父类构造 子类实例 子类构造
重写/覆盖/覆写Override:
- 函数名相同
- 参数列表相同
- 返回值相同
- 静态的方法和private不能被重写
注意:
- 子类的访问修饰限定符一定要大于等于父类的访问修饰限定符
- 父类的方法不能为私有
重载:
- 方法名相同
- 参数不同(类型和个数)
- 返回值不做要求
区别 | 重载(overload) | 重写(override) |
---|---|---|
范围 | 一个类 | 继承关系 |
限制 | 没有权限要求 | 子类的方法的访问权限不能低于父类的方法访问权限 |
区别 | super | this |
---|---|---|
概念 | 由子类访问父类中的属性或方法 | 访问本类中的属性、方法 |
查找范围 | 不查找本类而直接调用父类定义 | 先查找本类,如果本类没有就调用父类 |
特殊 | 无 | 表示当前对象 |
动态绑定
- 先向上转型 即父类的引用引用子类的对象 如重写一个eat()方法后,调用此方法。编译时父类方法 运行时却是子类方法(重写的),即实际调用打印的是子类方法
条件:
- 先要向上转型 即父类的引用引用子类的对象
- 父类和子类都有同名的覆盖方法,即重写
就会发生运行时绑定 - 编译时产生方法表 运行时方法表中子类的方法将父类的覆盖 即改变了地址,所以编译时父类方法 运行时却是子类方法
invokespecial 底层调用构造方法
invokevirtual 虚方法
invokestatic 静态方法
除静态方法和构造方法 其他都为虚方法
new出的对象在堆上 但是 Class的对象在方法区
抽象类(abstract)
abstract class Shape {
abstract public void draw();
}
- 在 draw 方法前加上 abstract 关键字, 表示这是一个抽象方法. 同时抽象方法没有方法体(没有 { }, 不能执行具体
代码). - 对于包含抽象方法的类, 必须加上 abstract 关键字表示这是一个抽象类.
注意事项:
1.包含抽象方法的类 叫做抽象类
2.抽象类和普通类最大的区别 包含抽象方法,也可以有普通方法
3.抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类. 然后让子类重写抽象类中的抽象方法.
4.抽象类存在的意义–》被继承
5.抽象类一旦被继承,就要重写抽象方法
6.如果一个类继承了抽象类,那么如果不想重写抽象类的方法,那么当前类需要设置为抽象类,可以选择重写,也可以不重写
7.抽象类不能加final
接口(interface):
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含静态常量.
interface IShape {
void draw();
}
class Cycle implements IShape {
@Override
public void draw() {
System.out.println("○");
}
}
public class Test {
public static void main(String[] args) {
IShape shape = new Rect();
shape.draw();
}
}
- 只能包含抽象方法 所以在接口里定于方法 ,默认为抽象的
- 定义的成员变量默认是public static final int a = 10; 方法 abstract void draw()
- 尽量简洁 不用加public static final 直接 int a = 10; 方法直接 void draw()
- 类和接口的关系是实现(implements),不能用extends,要用implements
- 一旦实现了接口,必须要重写方法
- 接口不能实例化 通过向上转型
- 多继承
- 接口与接口之间的关系为extends
- 子类访问修饰限定符要大于等于父类