Java笔经0:基本数据类型,访问修饰符,多态,构造器

注:这是本人笔试期间总结的一些java知识点,太简单的没写,太深奥的疏漏较多,主要是针对较难易错点的的一些探讨,错误之处还望留言斧正。

一、基本类型以及对应的包装类的各种转换、比较

1、各种规则

  • 自动类型转换顺序: byte/char/short -> int ->  long -> float -> double
  • 布尔型不参与自动类型转换

2、char、short、byte两两之间运算,都会转换为int

  • 一下代码做出验证
Object o = null;
short a = 3;
byte b = 2;
char c = 3;
o = a + b;
System.out.println(o.getClass().getName());     // java.lang.Integer
o = a + c;
System.out.println(o.getClass().getName());     // java.lang.Integer
o = b + c;
System.out.println(o.getClass().getName());     // java.lang.Integer
  • 由于向上转型,下边的第5、6行编译时就会报错:cannot convert from int to byte,为什么第4行可以呢?因为b3、b4都是final修饰的,在编译之后,这句就成了b5 = 7(也可能是b5 = 3 + 4,暂时还没搞清楚到底是是这两个哪一个,但是这两种形式都不会报错),自然没有问题
byte b1 = 1, b2 = 2;
final byte b3 = 3, b4 = 4;
byte b5;
b5 = b3 + b4;    // 正确
b5 = b3 + b5;    // 编译错误
b5 = b1 + b2;    // 编译错误

3、几种易错的赋值方法

  • 包装Long类型赋值需要加L,基本long无所谓
  • float的包装和基本类型都要加F
Long l = 1L;
long ll = 1;
Float f = 0.1F;
float ff = 0.1F;

4、包装类型的继承关系

二、访问控制符、修饰符

1、两个级别的访问控制符

  • 类级别:控制其他类能否使用该类。有2中类型:public  和 package-private(不写的话默认为此类型)
  • 成员级别:控制某一方法变量的访问,有4种类型: public , protected, package-private(默认default), private

2、类级别的 package-private

  • 也就是类没有访问控制符,这时该类除了能在本类中使用外,还能被同一个包中的其他类使用,不包括子包

3、成员级别修饰符

  该成员所在类 该成员所在包 其他包子类 任何地方
private Y N N Y
default Y Y N N
protected Y Y Y N
public Y Y Y Y

4、继承与访问修饰符

  • 父类方法为public,子类也必须为public
  • 父类为protected,子类必须为protected或者public
  • 父类中的private方法没有继承的说法,如下,这样编译都不会报错,但子类的eat()方法与父类的没有任何关系
class People{
    private void eat() {}
}

class Stu extends People{
    public void eat() {}
}
  • 子类继承方法的访问修饰符小于父类的范围时,编译报错,如下是错误的
class People{
    protected void eat() {}
}

class Stu extends People{
    private void eat() {}
}

5、接口

  • 接口的属性都是由public static final修饰
  • 接口的方法都是由public abstract修饰

6、成员内部类

  • 内部类可以有protected和private修饰符
  • 内部类拥有它所在外部类所有元素的访问权限。
  • 可以实现多重继承(内部类存在的最大理由之一)
  • 可以避免修改接口而实现同一个类中两种同名方法的调用

7、局部内部类

  • 不能加访问修饰符,因为它们不是类成员

8、静态内部类

  • 加static修饰符修饰

三、多态

1、子类重写、重载父类方法

  • 指向子类的父类引用由于向上转型了,它只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能使用的
  • 重载的方法返回值可以不同
class People {
    public int age() {
        return 0;
    }
    public int[] age(int i) {
        return new int[] {1};
    }
}
  • 若子类重写了父类中的某些方法,在调用该些方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)
public class Main {
    public static void main(String[] args) {
        People p = new Stu();
        p.eat();
        p.sleep();
        p.eat("apple");    // 编译错误
    }
    
}
class People{
    public void eat() {
        System.out.println("People eat");
    }
    public void sleep() {
        System.out.println("People sleep");
    }
}
class Stu extends People{
    // 重载
    public void eat(String food) {
        System.out.println("Stu eat " + food);
    }
    // 重写(覆盖)
    public void sleep() {
        System.out.println("Stu sleep");
    }
}

2、一个经典的多态例题

  • 这是一个非常经典的多态例子,A、B、C、D类的各种参数调用,代码如下
public class Main {
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        B b = new B();
        C c = new C();
        D d = new D();
        System.out.println(a1.show(b));     // A---A
        System.out.println(a1.show(c));     // A---A
        System.out.println(a1.show(d));     // A---D
        System.out.println(a2.show(b));     // B---A
        System.out.println(a2.show(c));     // B---A
        System.out.println(a2.show(d));     // A---D
        System.out.println(b.show(b));      // B---B
        System.out.println(b.show(c));      // B---B
        System.out.println(b.show(d));      // A---D
    }
}
class A {
    public String show(D obj) {
        return "A---D";
    }
    public String show(A obj) {
        return "A---A";
    }
}
class B extends A {
    public String show(B obj) {
        return "B---B";
    }
    public String show(A obj) {
        return "B---A";
    }
}
  • 首先贴上别人对这个的解释,也是我作为参考的,建议先看一下再回来接着看:https://blog.csdn.net/thinkGhoster/article/details/2307001
  • 继承链中对象方法的调用存在一个优先级:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)
  • 当超类对象引用变量 引用子类对象时,被引用对象的类型 决定了调用谁的成员方法,而不是引用变量的类型决定,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
  • 分析第四行:a2.show(b),a2是A类型的,所以去A中找方法show(B obj),发现没有,但是由于A类没有父类,所以不去父类中了,B的父类的A,接着去A类中找show(A obj)方法,发现有此方法,执行。
  • 分析第五行:a2.show(c),a2是A类型的,所以去A中找方法show(C obj),发现没有,但是由于A类没有父类,所以不去父类中了,C的父类的B,接着去A类中找show(B obj)方法,发现有此方法,但是此时a2是父类A的变量引用子类B的真实对象,所以是否调用A中show(B obj)方法,需要看子类B中是否重写(覆盖)了此方法,于是是B类中找show(B obj)方法,果真有覆盖了父类的方法,执行。
  • 分析第八行:b.show(c),b是B类型的,所以去B中找方法show(C obj),发现没有,于是去B的父类A去找show(C obj),发现也没有,因为C类的父类是B,接着去B类中找show(B obj),有此方法,执行。
  • 分析第九行:b.show(d),b是B类型的,所以去B中找方法show(D obj),发现没有,于是去B的父类A去找show(D obj),发现有此方法,执行。

四、构造器

  • 访问修饰符:可以有public、protected、default、private,不能有abstract、final、native、static、synchronized。
  • 在对象创建的时候才调用。
  • super和this:用super()调用父类的构造器,如果不写,默认也会加上,如果在父类中没有不带参数的构造器,子类的构造函数中有没有调用父类的构造器,编译就会报错。this()调用本类中的构造方法。super()和this()都要放在构造器的第一行。从本质上讲,this是一个指向本对象的指针, 然而super是一个Java关键字。
  • 构造代码块:对象构建是先于构造方法运行,可以抽取多个构造函数中的公共部分,减少代码量

猜你喜欢

转载自blog.csdn.net/DragonFreedom/article/details/82391698