面向对象

1 包
包是组织类的一种方式,保证类的唯一性。
如果代码中有相同的类,就会编译报错。这时可以放到不同的包中。
1.1 导入包中的类——Java提供了很多现成的类:

public class Test {
    public static void main(String[] args) {
        java.util.Date date = new java.util.Date();//java.util包中的Date类
         System.out.println(date.getTime()); 
    }
}

或者写成import语句导入包

import java.util.Date;
public class Test {
    public static void main(String[] args) {
        Date date = new Date(); //更加简洁
        System.out.println(date.getTime());
    }
}

如果遇上要用多个java.util包中的类,可以写成:
import java.util.*
1.2 静态导入
使用import static导入包中的静态方法和字段,例如:

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);
    }
}

1.3 包中的访问权限
当输入int a = 10;时,int前没有标明权限时,默认为default,只能访问在同一个包中的信息,无论在包中是否在同一个类里。

2 继承
为了方便代码调用。将公共代码放到一个单独的类中,让其他的类可以继承这个单独的类。这个单独的类里面包含的属性和方法,都自动被新的类支持进去。同时,新的类可以有自己独特的扩展。子类会继承父类所有的属性和方法。
2.1 基本语法
class 子类 extends 父类{
}
注意,一个子类只能继承一个父类。子类的实例中,也包含着父类的实例,可以使用super关键字得到父类实例的引用。
2.2 protected
继承中的封装,用portected关键字,无论是同一包中的子类还是不同包中的子类,都可以调用字段和方法。只有不同包的非子类才不能调用。
2.3 final
理论上可以无限制的继承下去,但一般不超过3,并且可以在最后一个子类加上final来表示该类无法再被继承。

3 多态
“一个引用,能表现出多种不同的形态”。当父类引用子类对象,并且父类和子类有同名覆盖的方法,这时,如果通过父类引用调用这个重名方法,就会发生动态绑定。封装是为了不让调用者知道类的实现细节(但还是知道是个啥类),多态更进一步,只要知道有某个方法就行。
3.1 向上转型
一个父类的引用指向一个子类的实例。例如:

class Animal{  //Animal父类 
    protected String name;
    public Animal(String name) {
        this.name = name;
    }
    public void eat(String food){
        System.out.println("我是一只小动物");
        System.out.println(this.name + "吃" + food);
    }
}
class Bird extends Animal{ //Bird子类
    public Bird(String name) { //继承父类属性
        super(name);
    }
    public void eat(String food){ //重写父类方法
        System.out.println("我是一只小鸟");
        System.out.println(this.name + "正在吃" + food);
    }
    public void fly(){  //子类特有方法
        System.out.println(this.name + "正在飞");
    }
}
public class test1 { //向上转型1
    public static void main(String[] args) {
        Animal bird = new Bird("小小鸟"); //直接赋值,父类引用指向子类实例,在这里发生向上转型
	bird.eat("谷子"); //父类必须有eat方法 ,发生动态绑定,重写父类eat方法
    }
}

运行结果为:
我是一只小鸟
小小鸟正在吃谷子

public class test2 { //向上转型2
    public static void main(String[] args) {
        Bird bird = new Bird("小小鸟");
        feed(bird); //方法传参
    }
    public static void feed(Animal animal){
        animal.eat("谷子");
    }
}

运行结果为:
我是一只小鸟
小小鸟正在吃谷子

public class test3 { //向上转型3
    public static void main(String[] args) {
        Animal animal = findMyAnimal();//方法返回
        animal.eat("小米");
    }
    public static Animal findMyAnimal(){
        Bird bird = new Bird("圆圆");
        return bird;
    }
}

运行结果为:
我是一只小鸟
圆圆正在吃小米
3.2 动态绑定
子类与父类中同时出现同名的方法,具体执行时调用哪个方法,就要看这个引用指向的是父类对象还是子类对象,这个过程是程序运行时决定的(不是编译期),因此成为动态绑定。test1中有所体现。
3.3方法重写
重写也可以叫覆写/覆盖(Override)。与重载不同。重写中子类的方法访问权限不能低于父类的访问权限。针对重写,可以用@Override来显示指定。

class Shape{ //父类
    public void draw(){ //父类方法
    }
}
class Cycle extends Shape{
    @Override //重写
    public void draw() {
        System.out.println("⚪");
    }
}
class Triangle extends Shape{
    @Override
    public void draw() {
        System.out.println("▲");
    }
}
class Flower extends Shape{
    @Override
    public void draw() {
        System.out.println("❀");
    }
}

public class test1 {
    public static void main(String[] args) {
        Shape shape1 = new Flower();
        Shape shape2 = new Cycle();
        Shape shape3 = new Triangle();
        drawShape(shape1);
        drawShape(shape2);
        drawShape(shape3);
    }
    public static void drawShape(Shape shape){
        shape.draw();
    }
}

最终结果为打印出三种形状。
使用多态的好处
(1)类的调用者对类的使用成本降低
(2)避免大量的if-else,降低全复杂度
(3)如需新增,改动成本低
3.4 向下转型
将父类的对象转为子类的对象

public static void main(String[] args) {
    Animal animal = new Bird("圆圆");
    animal.eat("谷子");
    //animal.fly(); //错误
    ((Bird) animal).fly(); //强转成Bird型,但不能转成Cat型
    //因为new出的是bird实例

编译过程中,animal的类型是Animal,因此,编译器只知道有一个eat方法,没有fly方法,虽然animal指向一个Bird对象,,但编译器是以animal的类型来查找方法。对于Animal animal = new Bird(“name”)这样的代码:(1)编译器检测有哪些方法的存在,只看Animal这个类型;(2)执行时到底执行父类还是子类,看的是Bird这个类型。

Animal animal1 = new Bird("扁扁");
    if (animal1 instanceof Bird) { //always true
        Bird bird = (Bird) animal1;
        bird.fly();
    }
    System.out.println("=============");
    Animal animal2 = new Cat("小猫");
    if(animal2 instanceof Bird){ //always false
        Bird bird1 = (Bird) animal2;
        bird1.fly();
    } // 不执行,new出的Cat实例,不是Bird
    System.out.println("-----------");
}

instanceof可以判定一个引用是否是某个类的实例,是就返回true,执行if中的语句。

4 抽象类
在3.3中父类Shape中的draw方法没有实际工作,绘制方法都是由子类的draw方法实现。这样的父类可以设计成一个抽象方法,包含抽象方法的类就被成为抽象类。

abstract class Shape{
    abstract public void draw();
}

draw方法前加上abstract关键字,表示这是一个抽象方法,同时抽象方法没有方法体(没有{},不能有具体执行的代码)对于包含抽象方法的类,必须加上abstract关键字表示这是一个抽象类。
注意:(1)抽象类不能直接实例化。
//Shape shape = new Shape(); //编译出错(2)抽象方法不能是private(3)抽象类中可以包含其他非抽象方法。

abstract  class Shape2{ //抽象类
    abstract public void draw(); //抽象方法,想要使用必须构建子类并在其中重写
    void func(){  //非抽象方法
        System.out.println("func()");
    }
}
class Rect extends Shape2{
    @Override
    public void draw() { //实现(重写)抽象方法
        System.out.println("draw(Rect)");
    }
}
public class test8 {
    public static void main(String[] args) {
        Shape2 shape2 = new Rect(); //向上转型
        shape2.func(); //非抽象
        shape2.draw(); //抽象
    }
}

运行结果:
func()
draw(Rect)
抽象类本身不能被实例化,要想使用,只能创建抽象类的子类,让子类重写抽象类中的抽象方法。

5 接口
接口是类的更进一步,抽象类中还可以包含非抽象方法,但接口中的方法都是抽象方法。字段只能包含静态常量。

interface IShape{
    public abstract void draw(); //public abstract可以省略
    public static final int num = 10; //public static final可以省略
}
class Cycle implements IShape{
    @Override
    public void draw() { //public不能省略
        System.out.println("⚪");
    }
}
public class test6 {
    public static void main(String[] args) {
        IShape shape = new Cycle();
        shape.draw();
    }
}

使用interface定义一个接口;方法一定是抽象的,可以省略abstract;方法一定是public的,可以省略public;Cycle用implements继承接口;调用时可以创建一个接口的引用,对应到一个子类的实例。接口不能被单独实例化。
在Java中只支持单继承,一个类只能extends一个父类,但可以同时实现多个接口,也能到达多继承类似的效果。

class Animal1{ //父类
    private String name;
    public Animal1(String name){
        this.name = name;
    }
}
interface IFlying{ //接口
    void fly();
}
interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}

class Cat1 extends Animal implements IRunning{ // 先继承 再接口
    public Cat1(String name) {
        super(name);
    }
    @Override
    public void run() {
        System.out.println(this.name + "正在用四条腿跑");
    }
}
class Fish extends Animal implements ISwimming{
    public Fish(String name) {
        super(name);
    }
    @Override
    public void swim() {
        System.out.println(this.name + "用尾巴游泳");
    }
}
class Frog extends Animal implements IRunning, ISwimming{
    public Frog(String name) {
        super(name);
    }
    @Override
    public void run() {
        System.out.println(this.name + "往前跳");
    }
    @Override
    public void swim() {
        System.out.println(this.name + "用腿游泳");
    }
}
class Robot implements IRunning{ //不用继承也可以实现接口
    private String name;
    protected Robot(String name) {
        this.name = name;
    }
    @Override
    public void run() {
        System.out.println(this.name + "用轮子跑");
    }
}
public class test7 {
    public static void main(String[] args) {
        Cat1 cat = new Cat1("小猫");
        walk(cat);
        Frog frog = new Frog("小青蛙");
        walk(frog);
        Robot robot = new Robot("机器");
        walk(robot);
    }
    public static void walk(IRunning running){
        System.out.println("去散步");
        running.run();
    }
}

接口之间也可以实现继承,甚至是多继承

interface IRunning{
    void run();
}
interface ISwimming{
    void swim();
}
interface IAmphibious extends IRunning,ISwimming{ //接口继承多个接口(extends)
}
class Frog implements IAmphibious{
//类和接口之间是实现(implements)
}

学生成绩排序

import java.util.Arrays;
class Student implements Comparable{
    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString(){
        return "[" + this.name + ":" + this.score + "]";
    }
    @Override
    public int compareTo(Object o) {
        Student s = (Student)o;
        if (this.score > s.score){
            return -1;
        }else if(this.score < s.score){
            return 1;
        }else{
            return 0;
        }
    }
}
public class test{
    public static void main(String[] args) {
        Student[] students = new Student[]{
                new Student("zhangsan",95),
                new Student("lisi",96),
                new Student("wangwu",97),
                new Student("zhaoliu",92),
        };
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }
}

附1 权限之间的区别
在这里插入图片描述
附2 重载与重写
在这里插入图片描述
附3 抽象类与接口
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值