【Java基础】学习笔记1 - 数据类型与面向对象基础

目录

    • 第一阶段
      • 自动类型转换
      • 强转
      • String 转换
      • 标识符命名规范
      • 原码、反码、补码
      • 数组
    • 第二阶段
      • 继承
      • Super
      • 重写 Override
      • 多态
      • 多态转型
      • 动态绑定

第一阶段

自动类型转换

多种数据混合运算,系统自动转换为容量大的数据类型后再执行计算

低精度数值赋值给高精度变量,执行自动转换;反过来不行,会报错

byte、short、char 之间不会发生相互转换

boolean 不参与转换


强转

数据精度从高到低,就需要使用强转

char 类型变量可以保存数字,但是你不能直接把 int 变量赋值给 char 变量


String 转换

你可以使用 string 类型的变量转换成任意类型的变量

如下代码

String str = "123";

int num1 = Int.parseInt(str);
float num2 = Float.parseFloat(str);

标识符命名规范

包名:所有字母均小写 com.zhiller.xxx

类名、接口名:大驼峰 FoodController

变量名、方法名:小驼峰 getName

常量:全大写,单词之间下划线隔开


原码、反码、补码

二进制最高位是符号位,0 负数,1 正数
正数的三个码都一样

负数反码:原码符号位不变,其余位取反
负数补码:反码+1

0 的反码补码均为 0


数组

创建数组

数组初始化器创建数组时,编译器会根据初始化器的元素个数动态计算数组长度,并为数组分配内存空间。
每个元素的值在编译时就确定了,并且在运行时直接被存储在数组对象中的连续内存位置上。

关键字 new 创建数组时,需要明确指定数组的长度,并在运行时动态分配内存空间。

// 数组初始化器
int[] arr1 = {1,2,3,4,5};

// 关键字new创建数组
int[] arr1 = new int[10];
arr1={1,2,34,5};

第二阶段

可变参数本质上就是一个数组
可变参数实参可以为 0 个或者任意多个

可变参数可以和普通参数放在一起,但是他必须要在所有参数的最后面(倒数第一个)

一个形参列表仅可存在一个可变参数

public int len(int... nums){
    return nums.length;
}

继承

子类继承所有属性和方法;
非私有属性和方法可以直接在子类访问;
私有属性必须通过父类公有方法来间接访问;

子类必须调用父类构造器完成初始化

子类默认调用父类无参构造,若父类不含无参构造,则需要借助 super 来指定一个构造函数

super()必须放在构造函数第一行

super()this()不可共存

Java 遵循单继承模式,子类只能继承一个父类!


Super

super 用于指代父类,如super.a就表示调用父类中的公开属性 a

父类中被定义为 final 的属性或方法将无法被重写

对于父类中的私有属性,可以在父类中添加对应的 gettersetter 方法,来让子类间接操纵它

public class SuperDemo {
    public static void main(String[] args) {
        B b = new B(12);
        b.canChange();
        b.cannotChange();
        b.setC(100);
        System.out.println(b.getC());
    }
}

class B extends A {
    public B(int num) {
        super(num);
        System.out.println(super.a);
    }

    @Override
    public void canChange() {
        System.out.println("i changed this method!!!");
    }
}

class A {
    int a, b;

    public int getC() {
        return c;
    }

    public void setC(int c) {
        this.c = c;
    }

    private int c;


    public A() {
        System.out.println("empty a");
    }

    public A(int num) {
        this.a = num;
    }

    public final void cannotChange() {
        System.out.println("this method cannot be changed");
    }

    public void canChange() {
        System.out.println("you can change this method");
    }
}


如果子类中有和父类重名的方法,则调用父类中重名方法时必须使用 super
若无重名方法,则用 super、this、直接指代都可以!!!

若直接调用方法,会先从当前类开始找,找不到再从父类中找,如果还找不到就一直迭代查询,直到 Object 类为止

若一条继承链上有许多类都出现了同名的方法,则最底层的类使用 super 调用同名方法时,遵循就近原则;
比如祖父类、父类、子类同时拥有同名方法,则 super 优先安装就近原则调度父类中的同名方法;


super 与 this 的比较

  • this 调用的都是本类中的属性和方法,除非子类没有,才不得不调用父类
  • super 直接调用的就是父类属性和方法

重写 Override

重写必背三大规定

  1. 子类方法名、参数要和父类完全一致
  2. 子类返回值类型必须和父类一样或者为父类返回值类型的子集
  3. 子类不可缩小父类访问权限(比如父类 public,子类重写不可以设置为 private)

访问权限大小对比:public>protected>default>private


多态

对于方法,可以存在两种多态形式

  1. 重载多态:定义同名方法,但参数数量不同,通过传参数量来使用对应的方法
  2. 重写多态:B、c 类同时继承 A 类,但俊重写了同名方法 zoo,那么实例化 B、C 类后,调用对应的同名方法就可实现重写多态

类的多态

对于一个对象,其编译类型和运行类型可以不一致;
编译类型看等号左边,运行类型看等号右边(如Animal dog = new Dog());
编译类型不可变动,但是运行类型可以改变;

public class PolyDemo {
    public static void main(String[] args) {
        Animal dog = getAnimal(new Dog());
        dog.cry();          // dog cry
        dog.walk("tom");    // tom
    }

    private static Animal getAnimal(Animal animal) {
        return animal;
    }
}

class Animal {
    public Animal() {
    }

    public void cry() {
        System.out.println("animal cry");
    }

    public void walk(String name) {
        System.out.println(name);
    }
}

class Dog extends Animal {
    public Dog() {
        super();
    }

    @Override
    public void cry() {
        System.out.println("dog cry");
    }
}

多态转型

向上转型:父类引用指向子类对象

Animal dog = getAnimal(new Dog());
此时可以访问父类 Animal 中的所有成员;
若子类还重写了父类中对应方法,那么访问方法时会优先使用子类中重写的方法;
不能访问在子类 Dog 中新定义的成员!!!(这里不包括子类重写的方法)


向下转型:子类执行父类的引用

转型后,可以调用子类中的所有方法;且转型内容必须是父类的引用而非父类的对象

Animal animal = new Animal();

Cat cat = (Cat) animal;

如果要检测某个对象是不是每个类的实例,可以借助 instanceOf
例如:dog instanceof Animal


动态绑定

动态绑定的基本原理:

  1. 当调用对象方法时,方法会和对象的内存地址与运行类型绑定
  2. 当调用对象属性时,无动态绑定,哪里声明就用那个

分析下方代码:

  • 定义父类 BindingA,其中有一个属性值 a=10
  • 定义子类 BindingB,重写方法 getNum,而且也同时定义了同名属性 a=20
  • 使用向上转型的方法,实例化对象 BindingB
  • 此时调用 getNum,因为方法存在动态绑定,故使用子类中重写的方法,返回 a+10
  • 由于属性无动态绑定,所以应该使用的是子类中定义的 a=20 而不是父类定义的 a=10,故结果返回 20+10=30
public class DynamicBinding {
    public static void main(String[] args) {
        BindingA b = new BindingB();
        System.out.println(b.getNum());  // 30
    }
}

class BindingA {
    public int a = 10;

    public BindingA() {
    }

    public int getNum() {
        return a;
    }
}

class BindingB extends BindingA {
    public BindingB() {
        super();
    }

    public int a = 20;

    @Override
    public int getNum() {
        return a + 10;
    }
}

你可能感兴趣的:(Java,java,学习,笔记)