文章目录
黑马全套Java教程(一)
黑马全套Java教程(二)
黑马全套Java教程(三)
黑马全套Java教程(四)
本博客配套黑马教学视频,视频可看B站,作为代码记录博客,从d175个视频开始,视频链接
18 抽象类
18.1 概述
在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类
例:抽象类和抽象方法定义,需要用abstract关键字
public abstract class Animal {
// public void eat(){
// System.out.println("吃东西");
// }
public abstract void eat(); //抽象方法
}
18.2 抽象类的特点
- 抽象类和抽象方法必须使用abstract关键字修饰
public abstract class 类名{}
public abstract void eat();
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 抽象类不能实例化
抽象类如何实例化?
参照多态的方式,通过子类对象实例化,这叫抽象类多态
代码如下:
Animal.java
//抽象方法的类一定是抽象类;抽象类里面不一定要抽象方法
public abstract class Animal { //抽象类
public abstract void eat(); //抽象方法
public void sleep(){
System.out.println("睡觉");
}
}
Cat.java
public class Cat extends Animal{ //继承抽象类
@Override
public void eat() { //重写抽象类里的抽象方法
System.out.println("猫吃鱼");
}
}
AnimalDemo.java
package myAbstract.Demo2;
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();
a.sleep();
System.out.println("----------------");
Cat b = new Cat();
b.eat();
b.sleep();
}
}
18.3 抽象类的成员特点
- 成员变量:可以是变量,也可以是常量
- 构造器:有构造器,但不能实例化。
- 成员方法:可以有抽象方法,用于限定子类必须完成某些动作;也可以有非抽象方法,提高代码复用性
那么,构造器的作用是什么呢?:用于子类访问父类数据的初始化
Animal.java
//抽象类
public abstract class Animal {
private int age = 20;
private final String city = "北京";
public Animal(){}
public Animal(int age){
this.age = age;
}
public void show(){
age = 40; //就近
System.out.println(age);
System.out.println(city);
}
public abstract void eat();
}
Cat.java
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
AnimalDemo.java
//测试类
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
a.eat();
a.show();
}
}
案例:猫和狗
Animal.java
package myAbstract.Demo4;
//抽象类
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
Cat.java
package myAbstract.Demo4;
public class Cat extends Animal{
public Cat() {
}
public Cat(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
Dog.java
package myAbstract.Demo4;
public class Dog extends Animal{
public Dog() {
}
public Dog(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
AnimalDemo.java
package myAbstract.Demo4;
//测试类
public class AnimalDemo {
public static void main(String[] args) {
Animal a = new Cat();
a.setName("加菲猫");
a.setAge(5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
System.out.println("-----------");
a = new Cat("橘猫", 6);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
}
}
19 接口
接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用
Java中的接口更多的体现在对行为的抽象
19.1 接口的特点
- 接口用关键字interface修饰,
public interface 接口名{}
- 类实现接口用implements表示:
public class 类名 implements 接口名{}
- 接口不能实例化
接口如何实现实例化?
参照多态的方式,通过实现类对象实例化,这叫接口多态
多态的形式:具体类多态,抽象类多态,接口多态
多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
接口的实现类:要么重写接口中的所有抽象方法;要么是抽象类
代码:
Jumpping.java
package myInterface.Demo1;
//定义了一个接口
public interface Jumpping { //换了关键字
public abstract void jump(); //public abstract可省略
}
Cat.java
package myInterface.Demo1;
public class Cat implements Jumpping{
@Override
public void jump() {
System.out.println("猫可以调高了");
}
}
Dog.java
package myInterface.Demo1;
public abstract class Dog implements Jumpping{
}
JumppingDemo.java
package myInterface.Demo1;
public class JumppingDemo {
public static void main(String[] args) {
//Jumpping j = new Jumpping(); //报错
Jumpping j = new Cat();
j.jump();
}
}
19.2 接口的成员特点
- 成员变量:只能是常量,默认修饰符
public static final
- 构造方法:接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在的
- 成员方法:只能是抽象方法,默认修饰符
public abstract
关于接口中的方法,JDK8和JDK9中有一些新特性,后面再讲解
Inter.java接口
package myInterface.Demo2;
public interface Inter {
public int num = 10;
public final int num2 = 20;
public static final int num3 = 30; //static和final可以不写的,默认有
int num4 = 40;
//接口没有构造方法
//public void show(){}
public abstract void method();
void show();
}
InterImpl.java
package myInterface.Demo2;
//public class InterImpl implements Inter{
public class InterImpl extends Object implements Inter{ //extends Object默认有
public InterImpl(){
super();
}
@Override
public void method() {
System.out.println("method");
}
@Override
public void show() {
System.out.println("show");
}
}
InterfaceDemo.java
package myInterface.Demo2;
//测试类
public class InterfaceDemo {
public static void main(String[] args) {
Inter i = new InterImpl();
//接口中成员变量 默认被final修饰,且被static修饰
//i.num = 20; //报错
System.out.println(i.num);
System.out.println(Inter.num);
System.out.println(i.num2);
}
}
案例:猫和狗
Jumpping.java接口
package myInterface.Demo3;
public interface Jumpping {
void jump();
}
Animal.java抽象方法
package myInterface.Demo3;
public abstract class Animal {
private String name;
private int age;
public Animal() {
}
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
Cat.java
package myInterface.Demo3;
public class Cat extends Animal implements Jumpping{
public Cat(){}
public Cat(String name, int age){
super(name, age);
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
Dog.java
package myInterface.Demo3;
public class Dog {
}
AnimalDemo.java测试类
package myInterface.Demo3;
//测试类
public class AnimalDemo {
public static void main(String[] args) {
//创建对象
Jumpping j = new Cat();
j.jump();
//j.eat(); //报错
System.out.println("--------------");
Animal a = new Cat("加菲猫", 5);
System.out.println(a.getName() + "," + a.getAge());
a.eat();
//a.jump(); //报错
System.out.println("----------------");
Cat c = new Cat("橘猫", 6);
c.eat();
c.jump();
}
}
19.3 类和接口关系
- 类和类关系:继承关系,只能是单继承,但是可以多层继承
- 类和接口关系:实现关系,但是单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
- 接口和接口关系:继承关系,可以单继承,也可以多继承
Inter1.java接口1
package myInterface.Demo4;
public interface Inter1{
}
Inter2.java接口2
package myInterface.Demo4;
public interface Inter2 {
}
Inter3.java接口3
package myInterface.Demo4;
public interface Inter3 extends Inter1, Inter2 {
}
InterImpl.java
package myInterface.Demo4;
public class InterImpl extends Object implements Inter1, Inter2, Inter3 {
}
19.4 抽象类和接口的区别
举例说明:
案例:运动员和教练
代码实现如下:
SpeakEnglish接口
package myInterface.Demo5;
//说英语的接口
public interface SpeakEnglish {
public abstract void speak();
}
Person抽象类
package myInterface.Demo5;
public abstract class Person {
private String name;
private int age;
public Person(){}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public abstract void eat();
}
Coach抽象类继承Person抽象类
package myInterface.Demo5;
//抽象教练类
public abstract class Coach extends Person{
public Coach() {
}
public Coach(String name, int age) {
super(name, age);
}
public abstract void teach();
}
Player抽象类继承Person抽象类
package myInterface.Demo5;
public abstract class Player extends Person{
public Player() {
}
public Player(String name, int age) {
super(name, age);
}
public abstract void study();
}
BasketballCoach.java
package myInterface.Demo5;
public class BasketballCoach extends Coach{
public BasketballCoach() {
}
public BasketballCoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("篮球教练教投篮");
}
@Override
public void eat() {
System.out.println("篮球教练吃羊肉");
}
}
BasketballPlayer.java
package myInterface.Demo5;
public class BasketballPlayer extends Player{
public BasketballPlayer() {
}
public BasketballPlayer(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("篮球运动员吃牛肉");
}
@Override
public void study() {
System.out.println("篮球运动员学习投篮");
}
}
PingPangCoach.java
package myInterface.Demo5;
public class PingPangCoach extends Coach implements SpeakEnglish{
public PingPangCoach() {
}
public PingPangCoach(String name, int age) {
super(name, age);
}
@Override
public void teach() {
System.out.println("乒乓球教练教发球");
}
@Override
public void eat() {
System.out.println("乒乓球教练吃小白菜");
}
@Override
public void speak() {
System.out.println("乒乓球教练说英语");
}
}
PingPangPlayer.java
package myInterface.Demo5;
public class PingPangPlayer extends Player implements SpeakEnglish{
public PingPangPlayer() {
}
public PingPangPlayer(String name, int age) {
super(name, age);
}
@Override
public void eat() {
System.out.println("乒乓球运动员喝小米粥");
}
@Override
public void study() {
System.out.println("乒乓球运动员学习打乒乓球");
}
@Override
public void speak() {
System.out.println("乒乓球运动员说英语");
}
}
20 形参和返回值
20.1 类名作为形参和返回值
- 方法的形参是类名,其实需要的是该类的对象
- 方法的返回值是类名,其实返回的是该类的对象
代码实现:
Cat.java
package myArgs.Demo1;
public class Cat {
public void eat() {
System.out.println("猫吃鱼");
}
}
CatOperator.java
package myArgs.Demo1;
public class CatOperator {
public void useCat(Cat c){
c.eat();
}
public Cat getCat(){
Cat c = new Cat();
return c;
}
}
CatDemo.java
package myArgs.Demo1;
//测试类
public class CatDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
CatOperator co = new CatOperator();
Cat c = new Cat();
co.useCat(c);
Cat c2 = co.getCat();
c2.eat();
}
}
20.2 抽象类名作为形参和返回值
- 方法的形参是抽象类名,其实需要的是该抽象类的子类对象
- 方法的返回值是抽象类名,其实返回的是该抽象类的子类对象
代码如下:
Animal.java
package myArgs.Demo2;
public abstract class Animal {
public abstract void eat();
}
AnimalOperator.java
package myArgs.Demo2;
public class AnimalOperator {
public void useAnimal(Animal a){
a.eat();
}
public Animal getAnimal(){
Animal a = new Cat();
return a;
}
}
Cat.java
package myArgs.Demo2;
public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
AnimalDemo.java
package myArgs.Demo2;
public class AnimalDemo {
public static void main(String[] args) {
//创建对象,调用方法
AnimalOperator ao = new AnimalOperator();
Cat a = new Cat();
ao.useAnimal(a);
Animal a2 = ao.getAnimal();
a2.eat();
}
}
20.3 接口名作为形参和返回值
- 方法的形参是接口名,其实需要的是该接口的实现类对象
- 方法的返回值是接口名,其实返回的是该接口的实现类对象
Jumpping.java
package myArgs.Demo3;
public interface Jumpping {
void jump();
}
Cat.java
package myArgs.Demo3;
public class Cat implements Jumpping{
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
JumppingOperator.java
package myArgs.Demo3;
public class JumppingOperator {
public void useJumpping(Jumpping j){
j.jump();
}
public Jumpping getJumpping(){
Jumpping j = new Cat();
return j;
}
}
JumppingDemo.java
package myArgs.Demo3;
//测试类
public class JumppingDemo {
public static void main(String[] args) {
//创建操作类对象,并调用方法
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.useJumpping(j);
Jumpping j2 = jo.getJumpping();
jo.useJumpping(j2);
}
}
21 内部类
21.1 概述
内部类:就是在一个类中定义一个类。
举例:在一个类A的内部定义一个类B,类B就被称为内部类
内部类访问特点:
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
按照内部类在类中定义的位置不同,可以分为如下两种形式:
- 在类的成员位置:成员内部类
- 在类的局部位置:局部内部类
代码:
package myInnerClass.Demo1;
/*
内部类格式:
public class 类名{
修饰符 class 类名{}
}
内部类的特点:
内部类可以直接访问外部类的成员,包括私有
外部类要访问内部类的成员,必须创建对象
*/
public class Outer {
private int num = 10;
public class Inner{
public void show(){
System.out.println(num);
}
}
public void method(){
//show(); //报错
Inner i = new Inner();
i.show();
}
}
21.2 成员内部类
成员内部类,外界如何创建对象使用呢?
- 格式:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
- 范例:
Outer.Inner oi = new Outer().new Inner();
代码一:
Outer.java
package myInnerClass.Demo2;
public class Outer {
private int num = 20;
public class Inner{
public void show(){
System.out.println(num);
}
}
}
InnerDemo.java
package myInnerClass.Demo2;
//测试类
public class InnerDemo {
public static void main(String[] args) {
//创建内部类对象并调用方法
Outer.Inner oi = new Outer().new Inner();
oi.show();
}
}
代码二:
Outer.java
package myInnerClass.Demo2;
public class Outer {
private int num = 20;
private class Inner{
public void show(){
System.out.println(num);
}
}
public void method(){
Inner i = new Inner();
i.show();
}
}
InnerDemo.java
package myInnerClass.Demo2;
//测试类
public class InnerDemo {
public static void main(String[] args) {
//创建内部类对象并调用方法
Outer o = new Outer();
o.method();
}
}
21.3 局部内部类
局部内部类是在方法中定义的类,所以外界是无法直接使用,需要在方法内部创建对象并使用
该类可以直接访问内部类的成员,也可以访问方法内的局部变量
Outer.java
package myInnerClass.Demo3;
public class Outer {
private int num = 10;
public void method() {
int num2 = 20;
class Inner {
public void show() {
System.out.println(num);
System.out.println(num2);
}
}
Inner i = new Inner();
i.show();
}
}
OuterDemo.java
package myInnerClass.Demo3;
//测试类
public class OuterDemo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
21.4 匿名内部类
局部内部类的一种特殊形式
前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类
interface接口
package myInnerClass.Demo4;
public interface Inter {
void show();
}
Outer.java
package myInnerClass.Demo4;
/*
前提:
存在一个类或者接口
这里的类可以是具体类也可以是抽象类
格式:
new 类名或者接口名(){
重写方法;
};
本质是什么呢?
是一个继承了该类或者实现了该接口的子类匿名对象
*/
public class Outer {
public void method(){
//多次调用
Inter i = new Inter(){
@Override
public void show() {
System.out.println("匿名内部类");
}
};
i.show();
i.show();
}
}
OuterDemo.java
package myInnerClass.Demo4;
public class OuterDemo {
public static void main(String[] args) {
Outer o = new Outer();
o.method();
}
}
匿名内部类在开发中的使用
Jumpping接口
package myInnerClass.Demo5;
/*
跳高接口
*/
public interface Jumpping {
void jump();
}
Cat.java
package myInnerClass.Demo5;
public class Cat implements Jumpping{
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
}
Dog.java
package myInnerClass.Demo5;
public class Dog implements Jumpping{
@Override
public void jump() {
System.out.println("狗可以跳高了");
}
}
JumppingOperator.java
package myInnerClass.Demo5;
//接口操作类,里面有一个发方法,方法的参数是接口名
public class JumppingOperator {
public void method(Jumpping j ){
j.jump();
}
}
JumppingDemo.java
package myInnerClass.Demo5;
public class JumppingDemo {
public static void main(String[] args) {
JumppingOperator jo = new JumppingOperator();
Jumpping j = new Cat();
jo.method(j);
Jumpping j2 = new Dog();
jo.method(j2);
System.out.println("----------");
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("猫可以跳高了");
}
});
jo.method(new Jumpping() {
@Override
public void jump() {
System.out.println("狗可以跳高了");
}
});
}
}
22 常用API
22.1 Math类
常用方法如下:
package myMath.Demo1;
/*
Math类的常用方法
*/
public class MathDemo {
public static void main(String[] args) {
//abs:返回绝对值, int a
System.out.println("int");
System.out.println(Math.abs(88));
System.out.println(Math.abs(-88));
System.out.println("----------------");
//ceil:返回大于或等于参数的最小double值,为整数, double a
System.out.println("ceil");
System.out.println(Math.ceil(12.34));
System.out.println(Math.ceil(12.56));
System.out.println("-----------------");
//floor:返回小于或等于参数的最大double值,为整数, double a
System.out.println("floor");
System.out.println(Math.floor(12.34));
System.out.println(Math.floor(12.56));
System.out.println("-----------------");
//round:按照四舍五入返回最接近参数的int
System.out.println("round");
System.out.println(Math.round(12.34F));
System.out.println(Math.round(12.56F));
System.out.println("-----------------");
//max(int a, int b):返回两者最大值
System.out.println("max");
System.out.println(Math.max(66, 88));
System.out.println("-----------------");
//min
System.out.println("min");
System.out.println(Math.min(66, 88));
System.out.println("-----------------");
//public static double pow(double a, double b):返回a的b次幂
System.out.println("pow");
System.out.println(Math.pow(2.0, 3.0));
System.out.println("-----------------");
//public static double random():返回值为double的正值,范围[0.0, 1.0)
System.out.println("random");
System.out.println(Math.random());
System.out.println(Math.random() * 100);
System.out.println((int) (Math.random() * 100));
System.out.println((int) (Math.random() * 100) + 1);
}
}
22.2 System类
System包含几个有用的类字段和方法,它不能被实例化
常用方法:
方法一:exit()
package mySystem.Demo1;
/*
System类的常用方法
*/
public class SystemDemo {
public static void main(String[] args) {
System.out.println("开始");
//public static void exit(int status):终止当前运行的JAVA虚拟机,非零表示异常终止
System.exit(0);
System.out.println("结束");
}
}
方法二:currentTimeMillis()
package mySystem.Demo1;
public class SystemDemo1 {
public static void main(String[] args) {
//public static long currentTimeMillis():返回当前时间(以毫秒为单位)
System.out.println(System.currentTimeMillis()); //毫秒值:当前时间与1970年之间的
System.out.println(System.currentTimeMillis()*1.0/1000/60/60/24/365+"年");
long start = System.currentTimeMillis();
for(int i =0;i<10000;i++)
{
System.out.println(i);
}
long end = System.currentTimeMillis();
System.out.println("共耗时:"+ (end-start)+"毫秒");
}
}
22.3 Object类
Object是类层次结构的跟,每个类都可以将Object作为超类。所有类都直接或者间接的继承自该类
构造方法:public Object()
回想面向对象中,为什么说子类的构造方法默认访问的是父类的无参构造方法?
因为它们的顶级父类只有无参构造方法
1. toString()方法
代码:
Student.java
package myObject;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
ObjectDemo.java
package myObject;
//Object是类层次结构的跟,每个类都可以将Object作为超类,所有类都直接或者间接的继承该类
//看源码的方法:选中,按下Ctrl+B
public class ObjectDemo {
public static void main(String[] args) {
Student s = new Student("林青霞",30);
System.out.println(s); //myObject.Student@49e4cb85
System.out.println(s.toString());
}
}
2. equals()方法
Student.java
package myObject.Demo2;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true; //比较地址是否相同
//判断参数是否为null 或者 判断两个对象是否来自同一个类
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o; //向下转型
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
}
ObjectDemo.java
package myObject.Demo2;
/*
测试类
public boolean equals(Object obj):指示一些其他对象是否等于此
*/
public class ObjectDemo {
public static void main(String[] args) {
Student s1 = new Student("林青霞",30);
Student s2 = new Student("林青霞",30);
System.out.println(s1==s2); //比较地址值
System.out.println(s1.equals(s2));
}
}
本博客到视频197截止!