Java基础篇
-
JDK、JRE和JVM的关系
JDK是java Development Kit,是Java程序的开发工具包,包含JRE和开发人员使用的开发工具。
JRE是Java Runtime Environment,是Java程序的运行环境,包含了JVM和运行时所需要的核心类库。
JVM是Java Virtual Machine,是java技术的核心。
-
java8大基本数据类型
整型 byte(1) short(2) int(4) long(8)
浮点型 float(4) double(8)
逻辑型 boolean
字符型 char(2)
引用数据类型包括:类、接口、数组,引用数据类型占用4个字节
String是final修饰的Java类,不可继承,属于引用数据类型 -
为什么byte的取值范围是-128~127
byte类型占1个字节,1字节=8bit,bit是描述电脑数据量的最小单位,在二进制中,一个0或者一个1就占用了一个bit,总共8bit,其中0代表正数,1代表负数
byte最大取值范围是01111111=127
byte最小取值范围是10000000=-128 -
java的特性之一
跨平台性:
java程序由即时编译器编译成字节码文件(.class),由java虚拟机(JVM)翻译成特定平台下的机器指令,具有“一次编译,到处运行”的特点。 -
Java的三大特点:继承、封装、多态
-
访问控制权限修饰符
public:公开的,全部都可以访问
protected:受保护的,可以访问本类中、同包下以及子类的方法
default:默认的,可以访问本类中、同包下的方法
private:私有的,只可以在本类中访问 -
重写和重载的区别(重点)
重写(Override):方法名、参数列表、返回值类型都相同,根据需求只修改方法体中的代码,把原来的父类方法覆盖掉,同时继承父类方法,使用super.可以访问父类中的属性和方法;子类方法的访问修饰符权限要大于父类的(public>protected>default>private);重写不能抛出新的异常。
总结:当子类继承了父类的方法,传入相同的参数,但程序做出了区别与父类方法的响应,并且还可以获取父类方法中的属性,体现了动态的多态性。
重载:重载是在同一个类中定义多个同名方法,方法名相同,访问修饰符可以相同也可以不同,参数列表的参数个数和类型顺序都不同,并与返回值无关。
(因此不能通过返回值来判断两个方法是否构成重载)
总结:调用方法是通过传入的参数个数和类型的不同,由程序去判断执行哪个方法,这体现了Java的多态性 -
Object类
所有类的基类。
1.toString()方法:
返回一个Java对象的字符串表现形式//源代码上toString的默认实现 public String toString(){ return this.getClass().getName()+"@"+Integer.toHexString(hashCode()); //返回的是 类名@对象的内存地址转换为十六进制的形式 }
JDK1.8的API文档中提到 一般建议重写toString()方法
2.finalize()方法
//源代码 protected void finalize () throws Throwable();
这个方法不需要程序员去手动调用,JVM的垃圾回收器负责调用这个方法,当一个Java对象即将被回收的时候,垃圾回收器会调用finalize()方法。
如果Java虚拟机并未面临内存消耗的情况,他是不会浪费时间去执行垃圾回收的以恢复内存,毕竟垃圾回收时是会影响程序的运行效率的
finalize()方法是一个为程序员准备的时机——垃圾销毁的时机,在垃圾销毁时想要执行一段代码的话,可以写在finalize()方法中。3.hashCode()方法
//源码 native方法 底层调用C++程序 public native int hashCode();
hashCode()方法返回的Java对象的虚拟内存地址
-
this和super关键字
this
this是一个引用,this的内存地址指向了自身
this可以出现在实例方法中(没有static修饰的方法),代表所在方法对当前对象的引用,一般可省略
this可以用来区分实例变量和局部变量 构造方法中的 this.id=id
this可以在构造方法中通过当前的构造方法调用其他的构造方法 this(实参)的格式,并且只能现在第一行
super
super可以访问父类中定义的属性
super可以调用父类中的成员方法
super可以在子类构造方法中调用父类构造方法,也要放在第一行
在多层继承中,super可以访问到直接或间接的父类
注意:通过this或者是super调用构造器,只能使用一个,因为他们的使用都必须放在首行
-
static(静态)关键字
static修饰的方法是静态方法,没有static修饰的方法是实例方法;
*访问静态方法用 “类名.”,访问实例方法用 “引用.”
判断方法使用需要用static修饰,要看该方法是否需要对象来执行,需要对象来执行的话就不加static属于实例方法,通过“引用.”的方式调用 *
static修饰的变量是静态变量,没有static修饰的方法是实例变量;
*访问静态变量用 “类名.”,访问实例变量用 “引用.” *静态代码块
static{ //静态代码块在类加载的时候执行,且只执行一次 }
-
final关键字
final修饰的类:为最终类,不被继承
final修饰的方法:不能被重写
final修饰的变量:叫常量,赋初始值之后不可改变 -
抽象类abstract
abstract修饰一个方法时,这个方法叫抽象方法;
abstract关键字修饰一个类时,这个类叫抽象类;
含有抽象方法的类必须声明为抽象类;
抽象类不能被实例化;
抽象方法只有方法的声明,没有方法的实现,抽象类是用来被继承的,由子类重写父类方法,并提供方法体;
public abstract int abstractMethod(int a) ;
子类继承抽象类之后,必须重写抽象类里的全部抽象方法;不能用abstract修饰属性、私有方法、构造器、静态方法、final的方法(final方法不能被继承,抽象方法与要重写)
-
接口interface
接口是特殊的抽象类;
接口中的方法都是抽象方法 ;
接口中只有抽象方法和常量;
接口中抽象方法的public abstract可省略,接口中常量的public static final可省略;
JAVA的继承特点
一个接口可以继承多个接口(多继承)interface A extends B,C{ }
一个类可以实现多个接口 interface A implements B,C{ }
一个类只能继承一个类 classB Extends classA
Java类是单继承的
Java接口可以继承多个接口 -
= =和equals的区别
= = 比较基本数据类型:值是否相同
= = 比较引用数据类型:引用地址是否相同
equals()只能比较引用类型:是否指向同一个对象
* 当equals()比较的是File、String、Date、Wapper(包装类)时,比较的时内容和类型,因为在这些类中重写了equals()方法 ;equals继承了Object类,可以重写equals()方法* -
两个对象的hashCode相同,equals()也一定为 true吗?
不对,两个对象的 hashCode()相同,equals()不一定 true。 -
java 中操作字符串都有哪些类?
操作字符串:String、StringBuffer、StringBuilderStringBuilder和StringBuffer的区别
String:底层是byte[]数组 但是final修饰的private final byte[] value;
是不可变的,每次进行String字符串拼接都会产生一个新的String对象
StringBuilder和StringBuffer底层是也是`byte[] value;
StringBuilder和StringBuffer都是可变字符序列,底层也是数组扩容问题。
StringBuffer:线程安全的(因此开销也大)。
StringBuilder:非线程安全的,效率高。摘自《JDK1.8API文档》
StringBuffer上的主要操作就是append和insert方法,可重载这些方法,已接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将这写字符串的字符添加或插入到字符串的缓冲区中。append方法始终将这些字符串添加到缓冲区的末端;insert方法则在指定的点添加字符。如何优化StringBuffer性能
StringBuffer实际上是用byte[]数组进行存储,并且初始化容量是16,在存储字符的时候是自动扩容的(通过数组拷贝这个方法arraycope)。在创建StringBuffer时尽可能给定一个初始化容量,尽量减少底层代码进行数组扩容的次数,预估记给一个合适的初始化容量(数组长度一旦确定不可更改,只能进行扩容)可以提高程序效率。//StringBuilder用法同下 //指定初始化容量的StringBuffer对象(字符串缓冲区对象) StringBuffer sb = new StringBuffer(50); //append追加字符串代替拼接字符串 sb.append("hello"); sb.append("world"); System.out.println(sb); //Output:helloworld
String、StringBuilder、StringBuffer三者的执行效率:
StringBuilder > StringBuffer > String
当然这个是相对的,不一定在所有情况下都是这样。
比如String str = “hello”+ "world"的效率就比 StringBuilder st = new StringBuilder().append(“hello”).append(“world”)要高。因此,这三个类是各有利弊,应当根据不同的情况来进行选择使用:
当字符串拼接操作或者改动较少的情况下,建议使用 String str="hello"这种形式;
当字符串拼接操作较多的情况下,建议使用StringBuilder,如果采用了多线程,则使用StringBuffer。 -
break、return、continue的区别
break跳出当前循环;
return种植当前方法;
continue跳出这次循环,直接进行下次循环; -
String(重点)
String类中的常用方法
String.charAt():返回指定索引处的char值
String.contains():判断前面字符串是否包含后面的字符串
String.equals():比较引用类型,比较的是内容和引用,比较Date,String,包装类的时候只比较内容
String.equalsIgnoreCase():比较两个字符串忽略大小写
String.indexOf(String s):返回当前字符串中s第一次出现的下标
String.lastIndexOf(String s):返回当前字符串中s最后一次出现的下标
String.isEmpty():判断某个字符串是否为空
String.length():返回字符串方法
String.replace(char oldChar,char newChar):用new char替换到所有old char所在的位置上,返回一个新的字符串
String.split():根据给定的字符串(或正则表达式)把字符串拆分,返回String一个数组
String.subString(int beginIndex):从beginIndex的位置开始往后截取到最后(下标从0开始)
String.subString(int beginIndex,int endIndex):从beginIndex的位置开始往后截取到endIndex-1的位置(左开右闭)
String.toCharArray():字符串转换成char[]数组
String.toLowerCase():将String所有的字符转换成小写
String.toUpperCase():将String所有的字符转换成大写
String.trim():去除字符串中的空白
String.valueOf():String类中唯一一个静态方法,不需要new新对象,把一个非字符串转成字符串 -
String的内存分配问题(相关面试题)
String s1 = "a"; String s2 = "b"; String s3 = "ab"; String s4 = "a" + "b"; String s5 = "a" + s2; //拼接符号前或后出现了变量s2,相当于在堆中new String(),所以s5和s3的内存地址不同 String s6 = s1 + s2; //s6:StringBuilder.append("a").append("b").toString()相当于是在堆中创建个新对象new String("ab") String s7 = new String("a") + new String("b");//相当于new String("ab") String s8 = s7.intern(); -----------------------------//在JDK1.8的环境中 System.out.println(s3 == s4); //true s3和s4是一样的,是存储在方法区的字符串常量池中的(串池中的对象唯一且不重复) System.out.println(s3 == s5); //false 但是s3.equals(s5)是true System.out.println(s3 == s6); //false s6在堆中 System.out.println(s3 == s7); //false System.out.println(s3 == s8); //true /* 解释后两个比较结果 String.intern()方法: 在JDK1.7/1.8中:将字符串对象尝试放入串池中,如果串池中有则不会放入,如果没有则放入,并把串池中的对象返回。 在JDK1.6中:将字符串对象尝试放入串池中,如果串池中有则不会放入,如果没有则复制一份放入,并把串池中的对象返回。 所以在这里串池中已经有“ab”(s3)了,则s7没有被放入串池还是在Java堆中,而返回的s8就是串池中的“ab” */
通过字节码文件分析new String(“a”) + new String(“b”)过程中创建了几个对象?
6个。
第一个:拼接字符串时首先会new StringBuilder()
第二个:常量池中的"a"
第三个:堆中new String(“a”)
第四个:常量池中的"b"
第五个:堆中new String(“b”)
第六个:堆中new String(“ab”)