2019-JAVA基础部分

第一章 JAVA基础部分

1.java平台无关性解释

C/C++之所以不能跨平台,就是因为C/C++源程序是对平台编译的,所以与平台密切相关。如果有这样的一个环境:它既可以向下兼容(对平台兼容),又可以向上兼容(程序可以运行),那么不就可以跨平台了吗。基于这样的原理,Java在计算机的操作系统上又提供了一个Java运行环境——JRE(安装JDK)。 JRE由Java虚拟机,类库和一些核心文件组成,也就是说,只要平台提供了Java运行环境,Java编写的软件就可以在其上运行。 和C/C++不同的是,Java语言提供的编译器不针对特定的操作系统和CPU芯片进行编程,而是针对Java虚拟机把Java源程序编译成称为字节码的“中间代码”,然后Java虚拟机负责将字节码翻译成虚拟机所在平台的机器码,并让当前平台运行该机器码。
Java语言能够一次编译,处处运行,也就是Java跨平台的原因
在一个计算机上编译得到的字节码文件(就是.class文件),可以复制到任何一个安装了Java运行环境的计算机上直接运行。然后字节码文件由虚拟机负责解释执行,即Java虚拟机将字节码翻译成本地计算机的机器码,然后将机器码交给本地的操作系统运行。

2.java程序初始化的顺利是怎样的

父类静态变量——父类静态代码块——子类静态变量——子类静态代码块——父类非静态变量——父类非静态代码块——父类构造函javascript:addNewTableRow()数——子类非静态变量——子类非静态代码块——子类构造函数

3.java的作用域有哪些

作用域与可见性当前类同一个package子类其他package
public✔️✔️✔️✔️
protected✔️✔️✔️
default✔️✔️
private

若父类与子类位于同一个包内,则子类对父类的default成员变量或方法有访问权限。不同包则没有访问权限。
KaTeX parse error: Invalid color: 'rgb(255,0,0)' at position 8: \color{r̲g̲b̲(̲2̲5̲5̲,̲0̲,̲0̲)̲}{注意}:修饰符只能修饰成员变量,不能来修饰局部变量。private和protected不能用来修饰类,只有public、abstract、final能用来修饰类。

4.什么是构造函数

构造函数是一种特殊的函数,用来在对象实例化时初始化对象的成员变量。特点有

  • 构造函数必须与类名相同,并且不能有返回值。
  • 每个类可以有多个构造函数,若开发人员没有提供构造函数,编译器在把源代码编译成字节码的过程中会提供一个无参构造函数。
  • 构造函数总是伴随着new操作一起调用,程序员不能自己调用,必须由系统调用。
  • 构造函数不能被继承,构造函数可重载(即构造函数的参数可以有0个,1个或多个)。
  • 子类可以通过super关键字来显示的调用父类的构造函数,若父类没有提供无参数的构造函数时,子类的构造函数中必须显式的调用父类的构造函数。若父类提供了无参数的构造函数,此时子类的构造函数就可以不显式的调用父类的构造函数,在这种情况下编译器会默认调用父类提供的无参数的构造函数。

5.object中的方法

Object类是一个特殊的类,是所有类的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认继承Object类 。object中的方法有getclass、hashcode、equals、clone、tostring、notify、notifyall、wait、finalize.

registerNatives() //对本地方法进行注册。
getClass() //返回此 Object 的运行类。
hashCode() //用于获取对象的哈希值。
equals(Object obj) //用于确认两个对象是否“相同”。
clone() //创建并返回此对象的一个副本。
toString() //返回该对象的字符串表示。
notify() //唤醒在此对象监视器上等待的单个线程。
notifyAll() //唤醒在此对象监视器上等待的所有线程。
wait(long timeout) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。
wait(long timeout, int nanos) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。
wait() //用于让当前线程失去操作权限,当前线程进入等待序列
finalize() //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
##6.什么是反射机制
Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信息和调用对象方法的功能称之为反射机制。也就是所谓在运行过程中获取类的字节码文件,有三种方式获取class类。

public class Test01 {
    public static void main(String[] args) {
        //第一种:通过实例.getClass()
        Test01 test01 = new Test01();
        Class<? extends Test01> aClass = test01.getClass();
        System.out.println(aClass.getName());//Test20190523.Test01
        //第二种:通过类名.Class
        Class<Test01> test01Class = Test01.class;
        System.out.println(test01Class.getName());//Test20190523.Test01
 
        try {
            //第三种:通过Class.forName("类的路径")
            Class<?> aClass1 = Class.forName("Test20190523.Test01");
            System.out.println(aClass1.getName());//Test20190523.Test01
        } catch (Exception e) {
            e.printStackTrace();
        }
 
    }
}

7.static关键字的作用

“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”——《java编程思想》
 这段话虽然只是说明了static方法的特殊之处,但是可以看出static关键字的基本作用,简而言之,一句话来描述就是:
 方便在没有创建对象的情况下来进行调用(方法/变量)。
 很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。
 static可以用来修饰类的成员方法、类的成员变量,另外可以编写static代码块来优化程序性能。
1)static方法
static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都是必须依赖具体的对象才能够被调用。
但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。
2)static变量
static变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。static成员变量的初始化顺序按照定义的顺序进行初始化。
3)static代码块
static关键字还有一个比较关键的作用就是 用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次。
为什么说static块可以用来优化程序性能,是因为它的特性:只会在类加载的时候执行一次!
注意:不能在成员函数内部定义static变量。
##8.final、finally和finalize有什么区别
1.final用于声明属性、方法和类,分别表示属性不可变、方法不可重写和类不可继承。其中属性不可变指的是引用不可变。
2.finally是异常处理的一部分,它只能用在try/catch中,并且附带一个语句块,表示这段语句最终一定被执行。
3.finalize是object的一个方法,在垃圾回收机制执行时会调用被回收对象的finalize方法,可以重写此方法来实现对其他资源的回收。
##9.volatile和instanceof有什么作用
volatile:是一个类型修饰符,他是被设计用来修饰被不同线程访问和修改的变量。被volatile类型定义的变量,系统每次用到它时都是直接从对应的内存中提取,而不是缓存。在使用了volatile修饰成员变量后,所有线程在任何时候所看到变量的值都是相同的。
instanceof:是一个二元运算符,它的作用是判断一个引用类型的变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例。
##10.int和Integer的区别
1、Integer是int的包装类,int则是java的一种基本数据类型
2、Integer变量必须实例化后才能使用,而int变量不需要
3、Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值
4、Integer的默认值是null,int的默认值是0
5、Integer的值缓存范围为-128~127
延伸:
关于Integer和int的比较
1、由于Integer变量实际上是对一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。

public class IntegerTest {
    public static void main(String[] args) {
        Integer a = new Integer(100);
        Integer b = new Integer(100);
        System.out.println(a == b);   //false
        System.out.println(a.equals(b));    //true
    }
}

2、Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)
3、非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池中的对象,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)

Integer integer3 = new Integer(200);
Integer j = 200;
System.out.println(integer3==j); false

4、对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false

11.equals,hashcode()和 == 的区别

1)若比较对象是值变量: == 常被用来比较基本数据类型(byte,int,short,long,float,double,char,boolean),变量直接存储的就是他们的值,所以 == 比较的就是他们的值,注意的是,基本数据类型不能用equals进行比较(equals是个函数,而基本类型不是对象)。
2)若比较对象是引用型变量:== 比较的是两个变量在堆中存储的地址是否相同。equals表示的是两个变量是否对同一个对象的引用,即堆中的内容是否相同。== 比较的是两个对象的地址,equals比较的是两个对象的内容,equals为true时,== 不一定为true。

equals是object的一个方法,创建的对象均可调用object的equals方法,但是使用equals方法时,要对它进行重写,否则它和==比较的效果一样。

hashcode()同样是object中的一个方法,它也是鉴定两个对象是否相等。object类中的hashcode方法返回对象在内存中地址转换成一个int值,所有如果没有重写hashcode方法,任何对象的hashcode方法都是不相等的。
总结:

== : 它的作用是判断两个对象的地址是不是相等。即,判断两个对象是不试同一个对象。
equals() : 它的作用也是判断两个对象是否相等。但它一般有两种使用情况(前面第1部分已详细介绍过):
情况1,类没有覆盖equals()方法。则通过equals()比较该类的两个对象时,等价于通过“==”比较这两个对象。
情况2,类覆盖了equals()方法。一般,我们都覆盖equals()方法来两个对象的内容相等;若它们的内容相等,则返回true(即,认为这两个对象相等)。
##12.String、StringBuffer和StringBuilder的区别
1)可变不可变
String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知。string对象是不可变的。private final char value[];
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。
2) 是否多线程安全
String中的对象是不可变的,也就可以理解为常量,显然线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的.
StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
在执行效率方面,StringBuilder最高,StringBuffer次之,String最低。如果要操作的数据量比较小,应优先使用string类;如果是在单线程下操作大量数据,则优先使用stringbuilder类;如果是在多线程下操作大量数据,则优先考虑StringBuffer。
StringBuffer初始化以及扩容机制:
1.StringBuffer()的初始容量可以容纳16个字符,当该对象的实体存放的字符的长度大于16时,实体容量就自动增加。StringBuffer对象可以通过length()方法获取实体中存放的字符序列长度,通过capacity()方法来获取当前实体的实际容量。
2.StringBuffer(int size)可以指定分配给该对象的实体的初始容量参数为参数size指定的字符个数。当该对象的实体存放的字符序列的长度大于size个字符时,实体的容量就自动的增加。以便存放所增加的字符。
3.StringBuffer(String s)可以指定给对象的实体的初始容量为参数字符串s的长度额外再加16个字符。当该对象的实体存放的字符序列长度大于size个字符时,实体的容量自动的增加,以便存放所增加的字符。
扩容算法
使用append()方法在字符串后面追加东西的时候,如果长度超过了该字符串存储空间大小了就需要进行扩容:构建新的存储空间更大的字符串,将之前的复制过去;
再进行字符串append添加的时候,会先计算添加后字符串大小,传入一个方法:ensureCapacityInternal 这个方法进行是否扩容的判断,需要扩容就调用expandCapacity方法进行扩容
尝试将新容量扩为大小变成2倍+2 if 判断一下 容量如果不够,直接扩充到需要的容量大小。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值