一、包
包是类的一种组织方式,主要目的是保证类的唯一性。(可以把包理解为装着各种类的文件夹)
1、导入包中的类:
示例:我们在没有导入Java工具包的时候直接使用Scanner类时,发现编译器会报错!
我们可以使用如下方法来使用Java工具包中的Scanner类
1-1、Java.util.[className]
public class TestDemo {
public static void main(String[] args) {
java.util.Scanner scanner = new java.util.Scanner(System.in);
}
}
1-2、使用import 导入Java中的工具类:
导入Scanner示例
代码如下:
import java.util.Scanner; //使用import导入工具包中的Scanner类;
public class TestDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
}
}
使用 * 导入所有工具类示例
代码如下:
import java.util.*; //使用import导入工具包中的所有类;
public class TestDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
}
}
有时我们直接使用import来导入类的时候会出现冲突的情况,因为图中的这个Date类在util 包和 sql 包中都存在,此时编译器无法知道我们用的是哪一个包中的Date类。
此时我们需要显示的指定要使用的类。
代码示例如下:
import java.util.*;
import java.sql.*;
public class TestDemo {
public static void main(String[] args) {
java.util.Date date = new java.util.Date();
}
}
1-3、静态导入
使用import可以导入包中静态的方法和字段
import static java.lang.System.*;
public class TestDemo {
public static void main(String[] args) {
out.println("heloworld");
}
}
2、把类放到包中
2-1、创建包的方法:
在弹出的对话框中输入包名(包名一般为小写且不要出现中文)
2-2、在包中新建一个类:
在新建的包名右键>>New>>JavaClass新建一个类,然后输入类名即可。
此时在新建的类的上方会显示包名
3、包的访问权限:
3-1、访问修饰限定符(public private protected default(包访问修饰符))
1、被public修饰的在任何地方都可以进行访问;
2、被protected修饰的可以在同一包中的同一类或者不同类,以及不同包中的子类被进行访问;
3、被private修饰的只能在同一包中的同一个类中进行访问;
4、default修饰的可以在同一包中进行访问;
二、继承
1.语法规则
class 子类 extend 父类{
}
子类也叫作派生类;
父类也称为 超类或者基类;
- Java中一个子类只可以继承一个父类(单继承);
- 子类会继承所有父类中被public修饰的方法和字段;
- 父类中被private修饰的字段和方法不会被子类继承;
- 子类也能够继承父类中的实例,可以使用super关键字来调用父类中实例的引用。
代码示例1:
public修饰父类成员变量
//定义一个Animal类;
class Animal {
//类的成员变量;
public String name;
//类中的方法:
public void eat(String food) {
System.out.println(name + "正在吃" + food);
}
}
//定义一个继承Animal类的Cat类;
class Cat extends Animal{
public void run(){
System.out.println(name + "奔跑");
}
}
//定义一个继承Animal类的Bird类;
class Bird extends Animal{
public void fly(){
System.out.println(name + "在天上飞");
}
}
public class TestDemo {
public static void main(String[] args) {
Cat cat = new Cat();
cat.name = "米米";
cat.eat("猫粮");
cat.run();
System.out.println("======================");
Bird bird = new Bird();
bird.name = "八歌";
bird.eat("虫子");
bird.fly();
}
}
代码执行结果:
代码示例2:
成员变量不添加修饰符时默认为包访问权限
public class TestDemo0422 {
public static void main(String[] args) {
Cat cat = new Cat("米米"); //实例化一个Cat类;
cat.imfor(2,"公"); //调用Cat类的方法;
System.out.println("===================");
cat.eat("猫粮"); //调用父类方法;
System.out.println("====================");
cat.run(); //调用Cat类中的run方法
}
}
class Animal {
//Animal类中的成员变量
String name ;
String sex;
int age;
//构造函数
public Animal(String name) {
this.name = name;
}
//类方法
public void eat(String food) {
System.out.println(this.name + "正在吃" + food);
}
}
//创建一个继承Animal类的不带任何成员变量的Cat类
class Cat extends Animal {
//重写父类构造方法
public Cat(String name) {
//使用super关键字调用父类的name成员变量
super(name);
}
//Cat类方法
public void run() {
System.out.println(this.name + "正在奔跑");
}
public void imfor(int age, String sex) {
this.age = age; //在Cat类中并没有定义age和sex成员变量,此处是Cat类继承了了父类中的age和sex成员变量
this.sex = sex;
System.out.println(this.name + "是一只" + this.age + "岁的" + sex + "猫");
}
}
使用private修饰父类的成员变量,子类就不能进行调用
运行结果:
如果使用public来修饰父类的成员变量,就会违背封装的初衷,此时我们使用protected关键字(访问权限:同一包中的类内部、子类、不同类;不同包中的子类能进行访问)来对父类成员变量进行修饰
class Animal1 {
protected String name;
protected int age;
//构造函数
public Animal1(String name) {
this.name = name;
}
}
class Dog extends Animal1 {
public Dog (String name) {
super(name);
}
public void show () {
System.out.println("狗的名字是" + this.name);
}
}
public static void main(String[] args) {
Dog dog = new Dog("花花");
dog.show();
}
运行结果:
在同一包中建立不同的类,用protecte修饰Animal类的成员变量在同一包中来实现访问
Animal类
public class Animal {
protected String name;
protected String sex;
protected int age;
public Animal(String name) {
System.out.println("父类的构造方法被调用了");
this.name = name;
}
public void eat(String food) {
System.out.println("父类的eat方法被调用了");
System.out.println(this.name + "正在吃" + food);
}
}
Cat类
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
public void run(String leg) {
System.out.println("正在用" + leg + "奔跑");
}
}
Bird 类
public class Bird extends Animal {
public Bird(String name) {
super(name);
}
public void fly(String wing) {
System.out.println(this.name + "正在用" + wing + "飞");
}
}
Test类
public class Test {
public static void main(String[] args) {
Cat cat = new Cat("米米");
cat.eat("猫粮");
cat.run("四条腿");
System.out.println("===================");
Bird bird = new Bird("八歌");
bird.eat("虫子");
bird.fly("翅膀");
}
}
运行结果:
定义一个Orange类继承Cat类
public class OrangeCat extends Cat {
//调用父类Cat类的构造函数
public OrangeCat(String name) {
//调用父类的成员变量
super(name);
}
//创建一个Orange类的方法
public void sleep() {
System.out.println(this.name + "正在睡觉");
}
}
public static void main(String[] args) {
OrangeCat orangeCat = new OrangeCat("橘子");
//调用Cat类的run方法
orangeCat.run("四条腿");
System.out.println("=======================");
//调用父类的eat方法
orangeCat.eat("猫粮");
System.out.println("=======================");
orangeCat.sleep();
}
final关键字
被final修饰的变量是常量,不能被修改
被final修饰的类不能够够被继承
//使用final修饰Animal类
final public class Animal {
protected String name;
protected String sex;
protected int age;
public Animal(String name) {
System.out.println("父类的构造方法被调用了");
this.name = name;
}
public void eat(String food) {
System.out.println("父类的eat方法被调用了");
System.out.println(this.name + "正在吃" + food);
}
}
此时我们运行Test会出现异常,Animal类无法被继承
2、多态
1、向上转型
1-1、直接赋值
代码示例:
向上转型可以理解为动物这个类别中包含狗这种子类别;
public class Test0422 {
public static void main(String[] args) {
//向上转型,animal引用指向了一个子类Dog的实例
Animal animal = new Dog("旺财");
//Dog(对象)的引用(dog)调用了父类中的eat方法
animal.eat("狗粮");
}
}
class Animal{
public String name;
public Animal(String name) {
System.out.println("父类的构造方法执行了");
this.name = name;
}
public void eat(String food) {
System.out.println("父类的eat()方法执行了");
System.out.println(name + "正在吃" + food);
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
public void bark() {
System.out.println(this.name = "汪汪");
}
}
向上转型时引用属于父类的类型,而在父类中并没有包括子类的特有方法,所以不能调用子类的特有方法(例如 不是所有的动物都会飞)
1-2 传值向上转型
public static void main(String[] args) {
Dog dog = new Dog("花花"); //dog引用指向Dog
func(dog); //传入参数dog到func中,传参后,func()的参数指向dog指向的对象名叫花花的 狗(对象)
}
public static void func(Animal animal) {
System.out.println(animal.name + "正在晒太阳");
}
1-3、方法返回
public static void main(String[] args) {
Animal animal = func(); //接收引用dog指向的对象
System.out.println("这个动物的名字叫做" + animal.name);
}
public static Dog func() {
Dog dog = new Dog("花花");
return dog;
}
2、动态绑定
当父类和子类中存在同名的方法,在进行调用时要区分出引用指向的是谁的对象。如果引用指向的是父类的对象,则调用父类的方法。指向子类对象就调用子类的方法。这个过程是程序运行时决定的而不是编译时决定的,所以称为动态绑定。
代码示例:
public class Animal {
protected String name;
protected String sex;
protected int age;
public Animal(String name) {
System.out.println("======父类的构造方法被调用了======");
this.name = name;
}
public void eat(String food) {
System.out.println("======父类的eat方法被调用了======");
System.out.println(this.name + "正在吃" + food);
}
}
public static void main(String[] args) {
//bird1这个引用指向Animal的对象
Animal bird1 = new Animal("八歌");
bird1.eat("鸟食");
//bird2这个引用指向Bird的对象
Animal bird2 = new Bird("黄鹂");
bird2.eat("虫子");
}
3、方法的重写
在动态绑定的例子中,子类实现和父类同名的方法,且参数类型、数量都一致,这就是方法的重写(也称为覆写、覆盖)override。
- 重写与重载是不一样的;
- 普通方法可以重写,static修饰的静态方和final修饰的方法不能重写;
- 重写的子类方法的权限不能低于父类方法的权限,同时,父类方法的访问修饰限定符不能是private;
- 重写的子类的方法的返回值不一定和父类的相同,但是建议一般要相同。
4、多态
作为类的创建者编写的部分:
定义一个父类Shape
public class Shape {
public void printShape() {
//啥都不用干
}
}
定义多个继承父类Shape的子类
public class Cycle extends Shape {
//重写父类方法
@Override
public void printShape() {
System.out.println("○○○○○○○○○○");
}
}
public class Flower extends Shape {
//重写父类方法
@Override
public void printShape() {
System.out.println("♣♣♣♣♣♣♣♣♣♣♣");
}
}
public class Hurts extends Shape {
//重写父类方法
@Override
public void printShape() {
System.out.println("♥♥♥♥♥♥♥♥♥♥♥");
}
}
public class Dalmons extends Shape {
//重写父类方法
@Override
public void printShape() {
System.out.println("◇◇◇◇◇◇◇◇◇◇◇");
}
}
//以下部分作为类的调用者编写
public class Test2 {
public static void main(String[] args) {
public static void main(String[] args) {
Shape shape0 = new Cycle();
Shape shape1 = new Dalmons();
Shape shape2 = new Flower();
Shape shape3 = new Hurts();
disPlayShape(shape0);
disPlayShape(shape1);
disPlayShape(shape2);
disPlayShape(shape3);
}
//类的调用者创建一个打印方法
public static void disPlayShape(Shape shape) {
shape.disPlay();
}
}
}
运行结果:
对于类的调用者来说,在编写disPlay打印方法的时候并不知道shape引用指向的是哪一个对象,此时shape调用printShape方法进行打印时可能会有多种情况,这具体要看shape引用指向的是哪一个类的实例,这就是多态。
三、抽象类
1、包含抽象方法的类就是抽象类,被abstract修饰的方法称为抽象方法。
语法规则:
public abstract class Shape {
public abstract void disPlay();
}
在dispaly方法前面加上一个abstract关键字,表示这是一个抽象方法,抽象方法没有方法体(也就是{}),不能执行具体代码。包含抽象方法的类Shape也需要用abstract关键字来修饰表示这是一个抽象类。
- 抽象类不能直接实例化,抽象类就是为了被继承而存在的。普通类可以被实例化,也可以被继承;
- 抽象类和普通类都可以被继承、向上转型、动态绑定;
- 抽象类当中的方法一定要被子类重写,而普通类被继承后,方法可以不被重写;
- 抽象类继承了一个抽象类,可以不重写父类的方法。如果这个抽象类再被一个普通类继承,那么在这个普通类中一定要重写父类的方法;
- 抽象类中的方法不能是private来修饰,因为会被无法继承。抽象类中除了包含抽象方法还可以包含普通方法和字段,这个普通方法可以被子类继承、重写或者直接调用。
抽象类的代码示例:
//类的编写者实现抽象类Shape及其子类等
public abstract class Shape {
//被abstract修饰的抽象方法
public abstract void disPlay();
//创建一个普通的方法
public void func() {
System.out.println("抽象类中的普通方法");
}
}
//类的调用者实现:
public static void main(String[] args) {
Shape shape0 = new Cycle();
Shape shape1 = new Dalmons();
Shape shape2 = new Flower();
Shape shape3 = new Hurts();
disPlayShape(shape0);
disPlayShape(shape1);
disPlayShape(shape2);
disPlayShape(shape3);
disPlay(shape0);
}
//创建一个打印方法
public static void disPlayShape(Shape shape) {
shape.disPlay();
}
public static void disPlay(Shape shape) {
shape.func();
}
运行结果:
四、接口
接口是抽象类的更进一步,使用interface关键字来定义接口。
代码示例:
public interface IShape {
int n = 10;
void display();
}
- 接口的名称以大写字母 I 开头,命名一般用形容词性;
- 接口不能被单独实例化;
- 接口中的方法默认一定是抽象方法,所以可以省略abstract;
- 接口中的方法默认一定是public,所以可以省略public;
- 接口中也可以有字段,但是一定要是静态常量,static和final可以省略,编程规范一般约定接口中的字段不加任何修饰符,保持代码的简洁性;
- 接口可以扩展接口(extends);
- JDK1.8以上版本,接口中可以定义被default修饰的普通方法;同样可以被类调用;
类使用implements来“继承接口” ,此时表达的含义不是扩展,而是实现
代码示例1:
public class Cycle implements IShape {
@Override
public void display() {
}
}
- 在Java中只支持单继承,也就是一个class只可以extends一个父类,但是可以implements多个接口;一个类可以继承另一个类同时实现多个接口;
代码示例:
//创建一个Animal 类
public class Animal {
String name;
public Animal(String name) {
System.out.println("======父类的构造方法执行了======");
this.name = name;
}
}
//定义一个代表会跑的接口
public interface IRunning {
void run() ;
}
//定义一个代表会飞的接口
public interface IFlaying {
void fly();
}
//定义一个代表会游泳的接口
public interface ISwimming {
void swim();
}
//创建一个Cat类继承Animal类并实现IRunning接口
public class Cat extends Animal implements IRunning {
//重写父类构造方法
public Cat(String name) {
super(name);
}
//重写接口方法
@Override
public void run() {
System.out.println(this.name + "正在奔跑");
}
}
//定义一个Frog类继承Animal类并实现两个接口
public class Frog extends Animal implements ISwimming,IRunning {
//重写父类构造方法
public Frog(String name) {
super(name);
}
//重写接口方法
@Override
public void swim() {
System.out.println(this.name + "正在水里游来游去");
}
@Override
public void run() {
System.out.println(this.name + "正在向前跳");
}
}
//定义一个Duck类继承Animal类并实现三个接口
public class Duck extends Animal implements ISwimming,IFlaying, IRunning {
//重写父类构造方法
public Duck(String name) {
super(name);
}
//重写接口方法:
@Override
public void fly() {
System.out.println(this.name + "飞起来了");
}
@Override
public void run() {
System.out.println(this.name + "正在用两只脚跑");
}
@Override
public void swim() {
System.out.println(this.name + "浮在水面上");
}
}
public class TestDemo {
public static void main(String[] args) {
Cat cat = new Cat("米米");
funcRunning(cat);
Frog frog = new Frog("王子");
funcSwimming(frog);
//上面两行代码也可以写成如下形式
funcRunning(new Frog("王子"));
funcRunning(new Duck("唐老鸭"));
funcSwimming(new Duck("唐老鸭"));
funcFlaying(new Duck("唐老鸭"));
}
//定义一个实现方法,参数为会跑的类
public static void funcRunning (IRunning running) {
running.run();
}
//定义一个实现方法参数为“会游泳的“类
public static void funcSwimming (ISwimming swimming) {
swimming.swim();
}
//定义一个实现方法,参数为会飞的
public static void funcFlaying(IFlaying flaying) {
flaying.fly();
}
}
运行结果:
代码示例2(实现Comparable 接口中的compareTo方法):
class Student implements Comparable<Student> {
String name;
int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) {
if (this.score > o.score) {
return 1;
}else if (this.score < o.score) {
return -1;
}else
return 0;
}
}
```java
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) {
Student[] students = new Student[]{
new Student("赵雷", 84),
new Student("钱电", 89),
new Student("孙风", 79),
new Student("李云", 94)
};
Arrays.sort(students);
System.out.println(Arrays.toString(students));
}
}
运行结果:
代码示例3