JAVA基础目录
目录
1.6 两个对象的 hashCode()相同,则equals()也一定为true?
1.8 操作字符串String、StringBuffer 和 StringBuilder 的区别?
1.14 重写(override)与重载(overload)的区别?
堆:被所有线程共享的一块内存区域,唯一目的就是存放对象实例。
1.18 int 转 String && String 转 int
前言
一、基础篇
1.1 JDK与JRE的区别?
- JDK:java 开发的工具包,提供了 java 的开发环境和运行环境。
- JRE:java 运行环境,为 java 的运行提供了所需环境。
- 具体来说:JDK 包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具。
- 简单来说:如果要运行java程序,只需要安装JRE;如果要编写java程序,就需要安装JDK。
1.2 Java中的八大基本类型以及封装类
基本类型 | 大小(字节) | 封装类 | 默认值 | 取值范围 |
---|---|---|---|---|
byte | 1 | Byte | (byte)0 | -128~127 |
short | 2 | Short | (short)0 | -32768(-)~+32767() |
int | 4 | Integer | 0 | -2147483648~+2147483647 |
long | 8 | Long | 0L | |
float | 4 | Float | 0.0f | 单精度,对小数部分精度要求不高 |
double | 8 | Double | 0.0d | 双精度,精确小数部分操作值大时 |
char | 2 | Character | \u0000(null) | 0~65535 |
boolean | 1 | Boolean | false | true,false |
1.3 int与Integer的区别?
- Integer是int的包装类;int是基本数据类型;
- Integer变量必须实例化后才能使用;int变量不需要;
- Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
- Integer的默认值是null;int的默认值是0。
1.4 ==与equals的区别?
- ==用来判断两个变量的值是否相等。如果变量是基本类型,则直接比较;如果变量时引用类型,则比较引用内存的地址。
- equals比较两个对象是否一样,实际上就是调用对象equals方法进行比较。equals默认情况下是引用比较,只是很多类重写了equals方法,比如String、Integer等把它变成了值比较,所以一般情况下equals比较的是值是否相等。
- 注意:Integer的高效效果(-127~+128范围)
1.5 hashCode的作用?
hashCode:就是对象的散列码,是根据对象的某些信息推导出的一个整数值,默认情况下表示是对象的存储地址。通过散列码,可以提高检索的效率,主要用于在散列存储结构中快速确定对象的存储地址,如Hashtable、hashMap中。
1.6 两个对象的 hashCode()相同,则equals()也一定为true?
- 不一定。两个对象的 hashCode() 相同,equals() 不一定 true。比如在map中,hashCode() 相等,只能说明这两个键值对的哈希值相同,不代表这两个键值对相等。例如:
String str1 = "Aa";
String str2 = "BB";
System.out.println(String.format("str1: %d | str2: %d",str1.hashCode(),str2.hashCode()));
System.out.println(str1.equals(str2));输出结果:
str1: 2112 | str2: 2112
false
两个对象equals返回true,那么hashcode一定相等;两个对象的hashcode相等,那么equals不一定为true。
重写equals()方法,则hashCode()方法也必须重写,这样才能保证equals()方法返回true时,hashcode的值相等。
1.7 final在Java中有什么作用?
- final 修饰的类为最终类,不能被继承。
- final 修饰的方法不能被重写。
- final 修饰的变量为常量,必须初始化,初始化之后的值不能被修改。
- 注:String 类有final修饰,也不能被继承,实现细节不允许改变。
1.8 操作字符串String、StringBuffer 和 StringBuilder 的区别?
String | StringBuffer | StringBuilder |
相同点:底层都是通过char数组实现的 | ||
String的值一旦创建是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间 | StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 | 可变类,速度更快 |
线程安全 | 线程不安全 | |
多线程系统中保证数据同步,但效率低 | 单线程操作字符串,效率高(不考虑线程安全) |
字符串反转:使用StringBuff 或者 StringBuilder 的 reverse()方法。
1.9 String 类的常用方法有哪些?
- length():返回字符串的长度;
- equals():字符串比较;
- replace():字符串替换;
- split():分隔字符串,返回一个分割后的字符串数组;
- substring():截取字符串
- indexOf():返回指定字符的索引;
- charAt():返回指定索引处的字符;
- toLowerCase():字符串转成小写字母;
- toUpperCase():字符串转成大写字母;
- trim():除去字符串两端的空白;
1.10 Files常用方法有哪些?
- Files.createFiles():创建文件;
- Files.createDirectory():创建文件夹;
- Files.delete():删除一个文件或目录;
- Files.copy():复制文件;
- Files.move():移动文件;
- Files.size():查看文件个数;
- Files.read():读取文件;
- Files.write():写入文件;
- Files.exists():检测文件路径是否存在。
1.11 类方法、实例方法、构造方法
Java中类的方法分为:类方法(用static修饰,也叫静态方法)、实例方法(没有static修饰,也叫非静态方法)
public static void myMethod(){};//类方法
public void myMethod2(){};//实例方法
public TestMybatis(){};//构造方法
实例方法与类方法的区别
1.类方法属于整个类,而不属于某个对象;
2.类方法只能访问类成员变量,不能访问实例变量,而实例方法可以访问类成员变量和实例变量;
3.在类方法中不能使用super、this关键字;
4.类方法的调用可以通过类名.类方法和对象.类方法,而实例方法只能通过对象.实例方法访问;
5.类方法只能访问类方法,而实例方法可以访问类方法和实例方法;
6.类方法不能被覆盖,实例方法可以被覆盖。
构造方法:负责对象的初始化工作,为实例变量赋予合适的初始值。
1.方法名与类名相同;
2.不要返回值类型;
3.不能被static、final、abstract、synchronized修饰,不能被子类继承;
4.当前类的其它构造方法通过this语句调用;
5.子类调用的构造方法通过super语句调用;
6.在程序中通过new语句调用。
1.12 Java创建对象有几种方式?
- new创建对象
- 通过反射机制
- 采用clone(克隆)机制
- 通过序列化机制
1.13 抽象类与接口的区别?
- 接口用interface关键字定义;抽象类用class关键字定义。
- 接口中的都是抽象方法(默认拼接:public abstract);抽象类中方法不限制。
- 接口中的变量都是公共的静态常量(默认加上:public static final );抽象类中变量是普通变量。
- 接口中没有构造方法,不能实例化,如果要实例化,接口变量必须指向实现类对象; 抽象类有构造方法,不能实例化,如果要实例化,抽象类变量必须指向子类的对象。
- 接口与接口可以多级继承,与类之间可以多实现;抽象类只能单继承。
1.14 重写(override)与重载(overload)的区别?
重写(override)
- 条件:发生在子类继承父类条件下。要求满足:两同两小一大。
- 两同:方法名、参数列表相同;
- 两小:子类返回类型小于等于父类;子类抛出异常小于等于父类;
- 一大:子类修饰符权限大于等于父类。(public>protected>default>private)
- 重写的意义:在不修改源码的情况下,进行功能的修改与拓展(OCP原则:面向修改关闭,面向拓展开放)
重载(overload)
- 条件:在同一个类中,存在方法名相同,参数列表不同的方法,构成重载。
- 重载的意义:是为了外界调用方法时方便,不管传入什么样的参数,都可以匹配到对应的同名方法
1.15 Java的四种引用,强弱软虚
强引用:使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:
1.String str = new String("str");
软引用:软引用在程序内存不足时,会被回收,使用方式:
1.// 注意:wrf这个引用也是强引用,它是指向SoftReference这个对象的,
2.// 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中T
3.SoftReference<String> wrf = new SoftReference<String>(new String("str"));
可用场景: 创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象。
弱引用:弱引用就是只要JVM垃圾回收器发现了它,就会将之回收,使用方式:
1.WeakReference<String> wrf = new WeakReference<String>(str);
可用场景: Java源码中的 java.util.WeakHashMap 中的 key 就是使用弱引用。可以理解为,一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。
虚引用:虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入ReferenceQueue 中。注意哦,其它引用是被JVM回收后才被传入ReferenceQueue 中的。由于这个机制,所以虚引用大多被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有 ReferenceQueue 。
1.PhantomReference<String> prf =
new PhantomReference<String>(new String("str"), new ReferenceQueue<>());
可用场景: 对象销毁前的一些操作,比如说资源释放等。Object.finalize() 虽然也可以做这类动作,但是这个方式即不安全又低效
上诉所说的几类引用,都是指对象本身的引用,而不是指 Reference 的四个子类的引用( SoftReference 等)。
1.16 Java自动装箱与拆箱
装箱就是自动将基本数据类型转换为包装器类型(int–>Integer);调用方法:
Integer
的valueOf(int)
方法
拆箱就是自动将包装器类型转换为基本数据类型(Integer–>int)。调用方法:Integer
的intValue
方法
1.17 Java方法区、栈、堆存储的信息
方法区:方法区与Java堆一样,是各个线程共享的内存区域。
存储信息:
- 类信息:类class、接口interface、枚举enum、注解annotation;
- 常量:static final修饰的成员变量都存储于方法区;
- 静态变量:静态变量随着类的加载而存在于方法区中;
- 方法:程序运行时会加载类编译生成的字节码,这个过程中静态变量(类变量)和静态方法及普通方法对应的字节码加载到方法区。
栈:线程私有的内存区域。
- 存储局部变量和引用
堆:被所有线程共享的一块内存区域,唯一目的就是存放对象实例。
- 由关键字new产生的所有对象都存储于堆中;
- 实例变量(非static修饰的成员变量)
示例
public class PersonDemo
{
public static void main(String[] args)
{ //局部变量p和形参args都在main方法的栈帧中
//new Person()对象在堆中分配空间
Person p = new Person();
//sum在栈中,new int[10]在堆中分配空间
int[] sum = new int[10];
}
}
class Person
{ //实例变量name和age在堆(Heap)中分配空间
private String name;
private int age;
//类变量(引用类型)name1和"cn"都在方法区(Method Area)
private static String name1 = "cn";
//类变量(引用类型)name2在方法区(Method Area)
//new String("cn")对象在堆(Heap)中分配空间
private static String name2 = new String("cn");
//num在堆中,new int[10]也在堆中
private int[] num = new int[10];
Person(String name,int age)
{
//this及形参name、age在构造方法被调用时
//会在构造方法的栈帧中开辟空间
this.name = name;
this.age = age;
}
//setName()方法在方法区中
public void setName(String name)
{
this.name = name;
}
//speak()方法在方法区中
public void speak()
{
System.out.println(this.name+"..."+this.age);
}
//showCountry()方法在方法区中
public static void showCountry()
{
System.out.println("country="+country);
}
}
1.18 int 转 String && String 转 int
int 转 String 有3种方式:
//(1)i+""
int i=10;
String s1 = i+"";
System.out.println(s1);
//(2)String.valueOf(i)
i=20;
String s2 = String.valueOf(i);
System.out.println(s2);
//(3)Integer.toString(i)
i=30;
String s3 = Integer.toString(i);
System.out.println(s3);
String 转 int 有2种方式:
//(1)Integer.parseInt(str1)
String str1 = "666";
int n1;
n1 = Integer.parseInt(str1);
System.out.println(n1);
//(2)
String str2 = "888";
int n2;
n2 = Integer.valueOf(str2).intValue();
System.out.println(n2);