Java 基础复习

https://www.bilibili.com/video/BV1Qb411g7cz?from=search&seid=7373469111232659208 参考的视频,整理出有用的一些点。

三种注释方式

变量的类型 基本数据类型 引用数据类型(数组、类、接口)

数组是数组引用类型的,操作数组的类是Arrays,里面实现了很多有用的方法

数组的静态初始化和动态初始化 new int[10]; / new int [] {1,2,3};

二维动态初始化必须指定第一维度大小 new int [10][];

jvm 中创建数组基本的堆栈结构变化

数组创建默认初始值 0/ false/ null

自动类型提升,强制类型转换

位运算中左移<< 右移>>(正数补0负数补1)是乘二除以二对关系(除二下取整数) 无符号右移>>>都补0

用异或运算实现两个数交换的骚操作,异或运算(或位运算)的一些性质对算法题有点帮助,如hashmap 里面hash值存入那个位置用的是(length-1)加&为运算,而length始终是2的幂。

局部变量在栈区,new 出来的东西在堆区

… 表示可变个数的形参, 接受0,1,2,…个参数,实际就是当做数组来处理。也可以直接传一个数组进去。 public void accept(String … agrs) {}

赋值的值传递,区别基本数据类型的传值和引用数据类型传地址

引用数据类型中的string字符串类型是比较特殊,由双引号表示的一个字符串,在内存中是存在一个常量池中,底层应该是用差数组来实现的,然后string在账中的变量存储的实际上就是一个地址值,之所以叫常量池,就是因为是不允许更改的,所以你新建一个string类型的字符串,实际上就是在常量池中又创建了一个字符串。所以字符串作为函数的形参的时候会和其他引用类型的变量体现出不一样的特性。但是作为参数的时候仍然符合直传递的一个特性。

封装性,private私有化不对外界暴露的成员变量、方法、初始化方法(e.g.单例模式)

private (类内可用)、缺省(同一个包可用)、protected(不同包的子类可用)、public 四种权限

可以用来修饰 属性、方法、构造器和内部类,修饰类(不包括内部类)只能用public和缺省。

类的属性初始化顺序

  • 默认初始化
  • 显式初始化 / 代码块(谁写在前先执行谁)
  • 构造器初始化(默认构造器的权限同类的权限)

this表示当前对象,可以修饰或者调用成员变量,属性以及构造器

this(形参列表),不能调用自己,并且必须在构造器的首行调用

package 表示类或接口所属的包,包名的命名规则和标识符相同,每.表示一层dir,同包名不能命名同名的类或者接口。import导入包名+类名,*导入包下的所有类。

java.lang包下的类可以不import,同包下的调用不用写import。异包同类只能用全类名的方式调用。import static java.lang.Math.*; import + static 调用类中的静态结构(属性或者方法)这个不常用。

继承可以避免冗余代码,易于功能扩展,是多态的基础。java中只允许单继承和多层继承。java.lang.Object是所有类的直接或者间接父类。子类可以重写覆盖父类方法

区别方法的重载和重写

重写时函数名参数列表都要相同,权限修饰符不小于父类被重写方法,父类private方法不可以被重写。返回值类型是void和基本数据类型是,重写方法也一致,如果是引用数据类型A,则重写方法的返回值可以是A或者A的子类,父类方法的异常也一样,重写方法抛出的异常也是一样或者子类。

super和this有点类似,可以修饰类的属性、方法和构造器。可以在子类的构造函数的第一行调用super(形参类表)的方式调用父类的构造器,和this()只能二选一。不写就会有默认的super(),子类不显示写构造方法就会自动调用父类的空参数构造器。

一个类如果有n个构造器,最多n-1的首行是this,至少一行是super。默认不写就是super。

子类的实例化过程,子类一定会直接或者间接的调用父类的构造器(n-1与1的关系),父类进而调用祖父类的,直到object。所以子类对象会继承所有父类的属性和方法。

多态,父类引用可以指向子类对象,父类引用只可以调用父类的方法,如果子类重写了该方法,则调用子类重写的。适用于方法,不适用于同名属性。

多态体现在执行的时候,属于一种动态绑定,是编译时期无法进行确定的。重载属于静态绑定,编译时期就可以确定,重写则无法在编译时期确定,解释运行时才可以确定,属于晚绑定。

instanceof关键字的使用,避免向下转型的时候出现异常

Object是所有类的直接或者间接父类,其中定义的属性(没有定义属性)和方法具有通用性

== 与 equals()的区别

==是一种运算符号

如果两边是基本数据类型,比较两边数值是否相同,int可以和double,char可以和int进行比较,除了布尔类型不能比较。

如果两边是应用类型的变量,则比较地址值是否相同,即是否是同一个对象。

equals是一种方法,不能使在基本数据类型上,在Objejct中类的定义是return(this == obj); 和==没有区别。

但是某个类重写了equals方法,则根据多态的动态绑定,执行的语句是重写的函数体。注意字符串和常量池的问题。equals中用getclass 比较会更严格 和 instance of 会存在漏洞(导致不同类对象,存在继承关系,返回的结果是true)。

to String 方法在object中默认返回类名和哈希值,子类可以重写,在print的时候被调用

基本数据类型和包装类,六种是number子类,自动装箱和拆箱

自动装箱与integer 缓存 -128-127

static关键字,静态变量随类加载,在JVM的方法区中的静态域里面放着

静态方法,随类加载。静态只能调用静态,非静态方法内部随便调用。

单例模式要求,私有化成员函数,唯一实例为静态,getInstance函数对外暴露,也为静态方法,分为懒汉式(类加载快但需要同步处理)和饿汉式(类加载慢但线程安全)两种方式。

main方法是程序入口,是一个静态方法,args参数接受的实际是命令行参数。

代码块(初始化块),不常用,就是一个大括号包裹的代码块,分静态和非静态。静态代码块随着类的加载而执行 (可存在多个,依声明顺序执行) 。非静态代码块随着对象的创建而执行,因此可以实现初始化功能。

类的属性初始化顺序:默认初始化、(显式初始化、 代码块(谁写在前面先执行谁))、构造函数

类的加载顺序,先加载父类(静态代码快)再加载子类(静态代码块),然后new 对象时先调用父类的非静态代码块和构造方法,再是子类的。

final关键字,可以修饰类,方法和变量。

修饰类则此类不能被其他类继承,不能有子类了。(e.g. String System StringBuffer类)

修饰方法则不能被重写,如getClass方法。

修饰属性就变成常量了,不能再修改。如果是属性只能用显式初始化/代码块/构造器中初始化

修饰局部变量,尤其是修饰形参时,不能再修改

static fianl 修饰属性,表示一个全局常量。

abstract 可以修饰类和方法。

abstract修饰类的时候,该类不能实例化,该类的非抽象子类可以实例化。

abstract修饰方法,e.g. public abstract void test(); 有抽象方法的类一定是抽象类。抽象类不一定有抽象方法。

若子类重写了父类的所有的抽象方法才可以实例化,否则子类也是抽象类。

abstract 不能和static、private 和 final共用。

抽象类的匿名子类对象

Person p = new Person(){
    @override
    public void eat(){
        System.out.println("吃饱饱");
    }
};

模版设计模式是抽象类的一种应用场景,实际中很多地方用到。

接口interface是和类class并列的一种结构,克服了类只能单继承的缺点,一个类可以实现多个接口。接口是一种规范,是多态的体现。

如果说类的继承是 is a 的关系, 实现接口更像 has a / can do 的关系,即具有某种特性或者功能。

interface中只能定义public final static 常量 和public abstract 抽象方法,不能有构造方法(JDK7 及之前)。

java类通过implement关键字取实现某个接口,该类需要重写interface中所有的抽象方法,否则该类退化为一个抽象类。接口之间可以多继承。应用场景e.g.JDBC面向接口编程。

接口的匿名实现对象和抽象类的匿名子类的书写形式差不多。

抽象类和接口的区别?…抽象类有构造器,接口没有。单继承与多实现。

接口与代理模式和工厂模式

一个类继承的类和实现的接口中有同名属性,类中调用要明确指出调用哪一个,如super. x 或者A. x

接口在JDK8中还可以有静态方法和默认方法

静态方法只能通过接口.静态方法名调用,接口实现类的对象无法调用,内部也访问不到,有点像把接口弄成工具类的意思。

默认方法就是一个普通的方法, 只可以通过实现类的对象进行调用。如果子类重写了,则调用重写的方法(多态)

interface Test{
    public final static int x = 0;
    public abstract void test();
    public static void test1(){}
    public default void test2(){}
}

如果父类和接口的默认方法出现同名,而子类没有重写,则优先调用父类的同名方法,类优先原则

如果两个接口有同名的默认方法,一个类实现这两个接口,并且没有重写,则调用该方法会报错,因为不知道调用哪个。如果非要调用:接口名.super.方法名()。

这里的知识点有点琐碎,看看得了。

内部类分为:成员内部类(静态、非静态),代码块内部类,局部内部类

以成员内部类为例,类内可以定义属性方法构造器等, 可以用final修饰,表示类不能被继承 ,abstract修饰表示不能实例化。

同时作为一个成员,可以调用外部来的一些属性和方法,可以被权限修饰符修饰

使用内部类使用频率很低,稍作了解。

局部内部类中调用局部变量时,局部变量应该声明成final,在安卓开发中比较常见。

Error不能显式处理,JVM内部出错,如栈溢出(无限递归),OOM(堆溢出)等

Exception分为编译时异常和运行时异常。常见运行时如角标越界,空指针,除零异常,类转换异常等。

两种处理方式,try-catch-finally (finally可选)和 throws。catch中的异常声明要按照先子后夫的顺序,否则unreachable。e.getMessage() e.printStacktrace()两个常用方法。

finally中的语句是一定会被执行的代码,即使catch里面又有异常或者代码在之前return了。fianlly里面有return会return final 里面的值。一般在finally写一些关闭资源的操作。

通常值处理编译时异常,否则无法通过编译,出现运行时异常的话,就是代码有问题,需要debug该代码了。

throws 是向上级抛异常,写在函数的参数列表后面。

子类重写父类方法是抛出的异常不能大于父类抛出的异常。

几个具有顺序依赖的方法要执行,而各个方法都可能抛出异常,这是各个方法不能各自用trycatch,而要throws,然后整体进行trycatch处理。

手动抛出异常关键字 throw new Exception(“msg”); 也可以自定义异常类等。

发表评论

电子邮件地址不会被公开。 必填项已用*标注