Java笔记

Java 笔记

  • 每个java源文件只能有一个public类型的类,并且此类要和文件名相同。

  • 实例变量永远都会有默认值,即使没有显式赋值。

默认值:

int     0
float   0.0
boolean false
引用      null
  • ==对于primitive主数据类型来说,是进行字节比较,而引用类型的话,则是比较是否引用的是同一个对象

  • java中跨类型转换(比如从String到int),需要调用内建类来完成转换。比如,Integer.parseInt("3")

  • for-in循环来遍历的时候,调用的只是副本

  • java的随机数由Math类的random()方法提供,产生一个介于0到1之间的小数。

  • 类似 (int) ,成为cast运算符,即强制类型转换。

  • 关于抽象类与抽象方法

    • Java天生支持(运行时多态),而C++则必须用 virtual 关键字修饰函数才能实现。

    • C++的纯虚函数才相当于Java的抽象方法。

    猜想:因为Java强制面向对象,所以不会有全局的函数,所以可能就不需要像C++那样来区分全局函数和成员函数。同理纯虚函数和函数声明可能也有类似的关系。

    扫描二维码关注公众号,回复: 49814 查看本文章

    猜想:非抽象类的所有成员都会被“构造出实体”,所以非抽象类才不能有抽象方法。Java这种用抽象类来约束抽象方法的行为,可能比C++那种反过来约束要好一些。

  • 关于继承与多态

    • java不允许多继承,所以一个类只可以继承(extends)一个普通类。但同时可继(implements)承多个接口。
    • java声明为父类的引用可以被赋值子类的实体,但是只能调用父类的方法。
  • 抽象类与接口

    • 抽象类允许有非抽象函数,即允许有被实际定义了的函数。
    • 接口则不允许有非抽象函数。
    • 子类只能继承一个抽象类,但可以继承多个接口。
    • 接口必须被实现,而抽象类可以被抽象类继承。
    • 类继承的概念是垂直的,而接口实现的概念是平行的。哈士奇类继承狗类,狗类继承动物类,哈士奇必是动物。

    所以使用接口必不会出现钻石继承,因为任何一个接口必没有父类(接口)

    • 而又由于接口必被实现,不能有父接口的存在,所以根本堆叠不起来,也就不会有垂直一说。所以,哈士奇类如果用接口来完成的话就是同时实现狗接口和动物接口。但这是不合理的,因为狗都是动物,它们是自然存在堆叠关系的。所以,哈士奇类实现犯二接口和嚎叫接口是合理的。

    可以看出,类和接口虽然类似但是根本不是同一种东西。类是确定的一以贯之的,就像商城里商品的分类,而接口是灵活的描述性的,就像商品的标签

  • 关于成员访问权限

    • 在java中,子类不能将父类成员方法的权限缩小,但可以放大(如protected变为public)。
    • 而成员变量的权限则不能被修改。

    因为假设一个接口定义了一套规则,保证一个实现此接口的任何一个子类都能有此方法可调用,但是若被子类改成private就尴尬了

  • 关于静态和非静态方法

    • 静态方法是属于类的,不属于单独的对象。
    • 非静态方法是属于每一个对象的,不属于类。

    其实,某种意义上说,静态方法就是过程式编程中的函数,即就想要某个特定的功能,而不属于什么客观事物关系。即使属于某个类也只是简单的分类,而没有逻辑上的堆叠关系,也就是说静态方法前的类名,一定意义上起了一个名字空间的作用。

    • 非静态方法可以调用静态方法,而静态方法则不能(直接)调用非静态方法(不论本类内外)。
    • 本类中非静态方法可以调用非静态方法,但不能(直接)调用其他类的非静态方法。
    • 静态方法任何时候都可以互相调用。

    其实以上问题就是个实例化的问题:非静态方法除了在本类非静态方法中,在其他任何地方的调用,都需先把类实例化为对象再调用。

  • 关于方法调用

有个很有意思的对比:

代码1public class ClassTest {
    public static void main(String[] args){
        A a = new B();
        a.get();
    }
}

class A{
    int a = 0;

    public void get(){
        System.out.println(a);
    }
}

class B extends A{
    int a = 1;
}

输出: 0

代码2public class ClassTest {
    public static void main(String[] args){
        A a = new B();
        a.get();
    }
}

class A{
    int a = 0;

    public void get(){
        System.out.println(a);
    }
}

class B extends A{
    int a = 1;

    public void get(){
        System.out.println(a);
    }
}

输出: 1

这说明了2个(其实是显而易见的)问题:

  1. 用父类的引用变量去操纵子类的对象时,方法优先用子类覆盖的版本(符合逻辑)。
  2. 而第一个例子也说明,实例变量的作用域只在类中。所以,本类的方法只能访问本类的变量(不附加其他任何条件的情况下)。

    • 关于常量的定义

    • 我的老师说,用static修饰的变量就是常量,其实不是的,因为它可以被子类覆盖而且还可以被静态方法修改。

    • 只有用final和static两个修饰符修饰的变量,才可以当常量使用。

    • 关于覆盖与重载

    • 覆盖是指重写一个与父类(或实现的接口)中方法形式(返回值和参数以及函数名)完全一致的新方法。

    • 而重载则是写一个与已存在方法同名但不同参数表的新方法。

所以下面这段代码既不是覆盖也不是重载,根本不会通过编译

class A{
    int a(){
        ...
    }
}

class B extends A{
    double a(){
        ...
    }
}

持续更新中…

猜你喜欢

转载自blog.csdn.net/JoeNahm/article/details/80052746