目录
包
1.静态导入
2.将类放到包中
3.包的访问权限控制
继承
基本语法:
注意事项:
protected 关键字
final 关键字
组合
多态
向上转型:
动态绑定
方法重写
重写的规则 :
注意事项 :
重载和重写的区别:
向下转型
super 关键字
1.使用了 super 来调用父类的构造器
2.使用 super 来调用父类的普通方法
super和this的区别
理解多态:
抽象类
语法规则
注意事项:
1.包含抽象方法的类,叫做抽象类.
2.什么是抽象方法,一个没有具体实现的方法,被abstract修饰.
3.抽象类是不可以被实例化的.
4.因为不能被实例化,所以,这个抽象类,其实只能被继承.
5.抽象类当中,也可以包含和普通类一样的成员方法.
6.一个普通类,继承了一个抽象类,那么这个普通类当中,需要重写这个抽象类的所有的抽象方法.
7.抽象类最大的作用,就是为了被继承.
8.一个抽象类A,如果继承了一个抽象类B,那么这个抽象类A,可以不实现抽象父类B的抽象方法.
9.结合第八点,当A类再次被一个普通类继承后,那么A和B这两个抽象类当中的抽象方法,必须被重写.
10.抽象类 不能被final修饰,抽象方法也不可以被final修饰.
接口
语法规则:
注意事项:
1.使用interface来修饰的.interface IA{}
2.接口当中的方法,不能有具体的实现.非要实现,只能通过关键字defaut来修饰这个方法.
3.在接口中,可以有static的方法.
4.里面的所有的方法都是public的.
5.抽象方法,默认是public abstract的.
6.接口是不可以通过new来实例化的
7.类和接口之间的关系是通过implements来实现的
8.当一个类实现了一个接口,就必须要重写接口当中的抽象方法.
9.接口当中的成员变量,默认是public staitc final修饰的
10.当一个类实现一个接口之后,重写这个方法的时候,这个方法前面必须加public
11.一个类可以通过关键字extens继承一个抽象类或者一个普通类,但是只能继承一个类,同时,也可以通过implements实现多个接口,接口之间使用 ,(逗号)隔开.
12.接口和接口之间可以使用extends来操作他们的关系,此时这里意为:拓展.
import java.util.*其中* 是通配符,需要谁就拿谁
使用import static可以导入包中的静态的方法和字段.(可读性差 不建议使用)
import static java.lang.System.*;
import static java.lang.Math.*;
public class Test {
public static void main(String[] args) {
out.println("hehhee");
out.println(max(10,20));
}
}
基本规则:
- 在文件的最上方加上一个 package 语句指定该代码在哪个包中.
- 包名需要尽量指定成唯一的名字, 通常会用公司的域名的颠倒形式(例如 com.bit.demo1 ).
- 包名要和代码路径相匹配.例如创建com.bit.demo1的包, 那么会存在一个对应的路径com/bit/demo1来存储代码.
- 如果一个类没有 package 语句, 则该类被放到一个默认包中.
我们已经了解了类中的 public 和 private. private 中的成员只能被类的内部使用.
如果某个成员不包含 public 和 private 关键字, 此时这个成员可以在包内部的其他类使用, 但是不能在包外部的类使用.
如果你的成员变量前面不加任何访问修饰符,它就默认为一个包的访问权限
例如:
package com.bit.demo1;
class Dog{
String name;
int age;
}
封装:不必要公开的数据成员和方法 使用private关键字进行修饰. 意义: 安全性.
继承:对公共性的抽取.使用extends关键字来进行处理的. 意义:可以对代码重复进行使用.
class 子类 extends 父类{
}
class Animal{
public int age;
public String name;
public void eat(){
System.out.println("吃吃吃");
}
}
class Dog extends Animal{
}
- 使用 extends 指定父类.
- Java 中一个子类 只能 继承一个父类 (而C++/Python等语言支持多继承).
- 子类会继承父类的所有 public 的字段和方法.
- 对于父类的 private 的字段和方法, 子类中是无法访问的.
- 子类的实例中, 也包含着父类的实例. 可以使用 super 关键字得到父类实例的引用.
- 当子类和父类中有重名的情况(成员变量),子类会优先考虑自己的.
- 子类继承了父类,那么子类在构造的时候,需要先帮助父类来进行构造.需要在子类的构造方法当中,使用super关键字来显示的调用父类的构造方法.
对于类的调用者来说, protected 修饰的字段和方法是不能访问的
对于类的子类和同一个包的其他类来说, protected修饰的字段和方法是可以访问的
包访问权限:什么都不写,只能在同一个包里面访问
如果一个类不想被继承可以用final修饰
例如:
//被final修饰,类不可以被继承
final class A{
final int age = 10;//常量被final修饰 不可以被修改
}
//err
class B extends A{
}
public class Test1 {
public static void main(String[] args) {
A a = new A();
a.age=20;//err
}
}
final 关键字的功能是限制 类被继承 "限制" 这件事情意味着 "不灵活". 在编程中, 灵活往往不见得是一件好事. 灵活可能意味着更容易出错. 是用 final 修饰的类被继承的时候, 就会编译报错, 此时就可以提示我们这样的继承是有悖这个类设计的初衷的.
我们平时是用的 String 字符串类, 就是用 final 修饰的, 不能被继承.
组合并没有涉及到特殊的语法(诸如 extends 这样的关键字), 仅仅是将一个类的实例作为另外一个类的字段. 这是我们设计类的一种常用方式之一.
组合表示 has - a 语义:
在刚才的例子中, 我们可以理解成一个学校中 "包含" 若干学生和教师.
继承表示 is - a 语义:
在上面的 "动物和猫" 的例子中, 我们可以理解成一只猫也 "是" 一种动物
一个 父类的引用 引用 子类的对象 这就是 向上转型
向上转型发生的时机 :
- 直接赋值
- 方法传参
- 方法返回
public class Test {
//作为方法传参
public static void func(Animal animal){
}
//作为方法返回
public static Animal func2(Animal animal){
return animal;
}
public static void main(String[] args) {
//直接赋值
Animal animal = new Dog("dddddoog",200);//父类引用 引用 子类对象
Dog dog = new Dog("www",20);
func(dog);
}
}
父类引用 引用子类对象 且 父类和子类 有同名的覆盖方法.通过父类引用调用这个同名的覆盖方法.就会发生运行 动态绑定.
package com.bit.demo2;
class Animal{
public String name;
public void eat(){
System.out.println(name+"吃吃吃");
}
}
class Dog extends Animal{
public void eat(){
System.out.println(name+"L狼吞虎咽");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog("www",20);
animal.eat(); //运行时是运行Dog子类对象中的eat()
}
}
如上面代码,父类引用animal 引用了子类对象 Dog,且有同名的覆盖方法,eat(),当通过父类调用这个方法的时候,就会运行 动态绑定
针对刚才的 eat 方法来说: 子类实现父类的同名方法, 并且参数的类型和个数完全相同, 这种情况称为 覆写/重写/覆盖(Override).
- 方法名相同
- 返回值类型相同
- 参数的类型及个数
- 继承关系(父子类的情况下)
- 被重写的方法不能拥有比父类更严格的访问限制权限
- 普通方法可以重写, static 修饰的静态方法不能重写.
- 子类的访问修饰符限定,要大于等于父类的访问修饰限定
- private方法不能重写
- 被final修饰的方法不能重写
- 重写的方法返回值类型不一定和父类的方法相同(但是建议最好写成相同, 特殊情况除外).
通过父类引用 只能访问父类自己的成员;
就是 父类对象 转换成 子类对象
public static void main(String[] args) {
Animal animal = new Bird("hhe",200,"起飞起飞");
Bird bird = (Bird) animal;
bird.fly();
}
super 表示获取到父类实例的引用. 有2种常见方法:
class Bird extends Animal {
public String wing;
public String name;
public Bird(String name,int age,String wing){
super(name,age);
this.wing = wing;
}
}
class Animal {
public String name;
public int age;
public void eat(){
System.out.println("吃吃吃吃吃吃");
}
}
class Bird extends Animal {
public String name;
@Override
public void eat() {
super.eat();
System.out.println("小鸟吃吃吃");
}
}
通过一个引用调用同一个draw方法,因为引用的对象不一样表现出的形式各不相同
class Shape {
public void draw(){
System.out.println("shape::shape");
}
}
class Rect extends Shape{
@Override
public void draw() {
System.out.println("♦");
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("❀");
}
}
public class Test {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Rect ret = new Rect();
drawMap(ret);
Flower flower = new Flower();
drawMap(flower);
}
}
多态顾名思义, 就是 "一个引用, 能表现出多种不同形态"
一个引用到底是指向父类对象, 还是某个子类对象(可能有多个), 也是要根据上下文的代 码来确定.
在刚才的打印图形例子中, 我们发现, 父类 Shape 中的 draw 方法好像并没有什么实际工作, 主要的绘制图形都是由 Shape 的各种子类的 draw 方法来完成的. 像这种没有实际工作的方法, 我们可以把它设计成一个 抽象方法(abstract method), 包含抽象方法的类我们称为 抽象类(abstract class).
abstract class Shape {
abstract public void draw();
}
//抽象类
abstract class Shape{
public abstract void draw();//抽象方法
}
接口是抽象类的更进一步. 抽象类中还可以包含非抽象方法, 和字段. 而接口中包含的方法都是抽象方法, 字段只能包含 静态常量.
interface IShape{
void draw();
}
class Cycle implements IShape{
@Override
public void draw() {
System.out.println("○");
}
}
一个接口B 通过 extens来 拓展另一个接口A的功能.此时当一个类C通过implements实现这个接口B的时候,此时重写的方法不仅仅是B的抽象方法,还有其他从C接口,拓展来的方法(功能).