1、Java创建对象的几种方式?
java提供了四种创建对象的方式:
成员类:
public class User {
private String name;
}
-
new创建对象
User user = new User();
-
通过反射机制创建对象
Class<User> user = User.class;
-
采用clone机制
private static User user = new User();
-
通过序列化机制
2、有没有可能是两个不相等的对象有同样的hashcode
hashcode:
是对象的哈希码(散列码),默认情况下hashCode返回的是对象的存储地址映射成一个数值,也可以重写hashCode方法来实现自己的哈希码(散列码)逻辑,通过哈希码(散列码),可以提高查询的效率,主要用于在哈希表(散列表)结构中快速确定对象的存储地址,如HashMap
、HashSet
中。
有可能,在产生``hash冲突的时候,有两个不相等的对象就会有相同的
hashcode`,一般由下面几种方法来处理:
public class Demo {
public static void main(String[] args) {
System.out.println("Aa".hashCode());
System.out.println("BB".hashCode());
}
}
两者的hashcode值都是为:2112
拉链法:每个哈希表节点都由一个next
指针,多个哈希表节点可以用next
指针构成一个单向链表,呗分配到同一个索引伤的多个节点可以用这个单向链表进行存储。
开发定值法:一旦发生了冲突,就会寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将记录存入。
**再哈希:**又叫做双哈希表,又多个不同的hash函数,发生冲突时,使用第二个,第三个…等哈希数计算地址,直到无冲突
hashmap的用法:
public class Demo {
public static void main(String[] args) {
HashMap<String, User> stringUserHashMap = new HashMap<>();
User value = new User();
stringUserHashMap.put("张三", value);
stringUserHashMap.put("李四",new User());
//获取其键
System.out.println(stringUserHashMap.keySet());
//获取其键值
System.out.println(stringUserHashMap.entrySet());
//删除其值
System.out.println(stringUserHashMap.remove("张三"));
System.out.println(stringUserHashMap.keySet());
}
}
---------------------------
3、深拷贝和浅拷贝的区别是什么?
- 浅拷贝:被复制对象的所有遍历都含有与原来的对象相同的值,而所有的对象依然指向原来的对象。简而言之:浅拷贝仅仅是复制所考虑的对象,而不复制他所应用的对象。
- 深拷贝:被复制对象的所有变量都含有与原来相同的对象相同的值。而哪些应用其他对象的变量将只想被复制过的新对象。而不再是原有的哪些被引用的对象。简而言之:深拷贝把要复制的对象所引用的对象都复制了一遍。
4、final有哪些用法?
- 被final修饰的类无法被继承
- 被final修饰的方法不可以被重写
- 被final修饰的变量不可以被改变。如果修饰引用,那么表示引用不可变,引用指向的内容可变。
- 被final修饰的方法,jvm会尝试将其内联,以提高效率
- 被final修饰的常量,在编译阶段会存入常量池中
在构造函数内对final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量。这两个操作之间不能重新排序,初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。
5、static的用法
static
关键字的用法:静态变量和静态方法(也就是被static
修饰的方法或者变量)
被static
修饰的都属于类的静态资源,类实例所共享。
除了静态变量与方法之外,static也用于静态块,出用于初始化操作:
public class Demo {
static {
System.out.println("你好");
}
public static void main(String[] args) {
System.out.println("张三");
}
}
结果:你好
张三
结论:被`static`修饰的静态块优先执行
此外static
也多用于修饰内部类,此时被称为静态内部类
静态导包:即import static
.import static
是在JDK1.5之后引入的新特性,可以用来指定导入某个类的静态资源,并且不需要使用类名,可以直接使用资源名。如:
import static java.lang.Math.*;
public class Demo {
public static void main(String[] args) {
int a = (int)(Math.random()*100);
System.out.println(Math.abs(-2));
System.out.println(abs(-2));
}
}
6 、3*0.1==0.3返回值是什么?
false,因为有些浮点数不能被完全精确的表示出来
float a = 3.0f;
float b = 0.1f;
System.out.println(3*0.1==0.3);
System.out.println(3*0.1);
System.out.println(a*b);
答案:false
0.30000000000000004
0.3
至于为什么是 0.30000000000000004
有兴趣的可以看下下面这篇博客
为什么java里面30.1=0.30000000000000004,而40.1=0.4?_那些年的代码的博客-CSDN博客
7、a=a+b与a+=b有什么区别
+=
操作符回进行隐式自动类型转换,此处a+=b隐式的将家操作的结果类型强制将转为只有结果的类型,而a=a+b则不会自动进行类型转换。如:
byte a = 127;
byte b = 127;
b = a+b; //java: 不兼容的类型: 从int转换到byte可能会有损失
System.out.println(b);
System.out.println(b+=a);
如下列代码:
short s1 = 1;
s1 = s1+1;//java: 不兼容的类型: 从int转换到short可能会有损失
System.out.println(s1);
会报错,short
类型在进行运算时会自动提升为int类型,也就是说s1+1的结果类型时int
类型,而s1是short
类型,此时编译器就会报错
正确写法:
short s1 = 1;
s1+ =1;//java: 不兼容的类型: 从int转换到short可能会有损失
System.out.println(s1);
结果:
2
+=操作符会对右边的表达式结果强制匹配左边的数据类型,所以没错。
查看s1的数据类型:
public class Demo {
public String getType(Object object){
return object.getClass().toString();
}
public static void main(String[] args) {
Demo demo = new Demo();
short s1 = 1;
s1 +=1;
System.out.println(demo.getType(s1));
}
}
结果:
class java.lang.Short
8、try catch finally,try里面有return,finally还执行吗?
执行,并且finally
的执行早于try
里面的return
public class Demo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int age =0;
try {
System.out.println("输入年龄:");
age=scanner.nextInt();
}catch (Exception e){
System.out.println("输入有误");
}finally {
System.out.println("输入成功!");
}
}
}
当输入:张三
返回值:输入有误
输入成功!
当输入:12
返回值:输入成功!
结论:
- 不管有没有出现异常,
finally
块中的代码都会执行 - 当
try
和catch
中有return
时,finally
仍然会执行 finally
是在return
后面的表达式运算后执行的,所以函数返回值在finally
执行前确定的finally
中最好不要包含return
,否者程序会提前退出,返回值不是try
或catch
中保存的返回值。
9、简述线程、程序、进程的基本概念。以及他们之间关系是什么?
**线程:**线程与进程相似,但是比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。是一对多的关系。与进程不同的是,同类的多个线程公用同一块内存空间和一组系统资源,所以系统在产生一个线程,或者在各个线程之间切换时,负担要比进程小得多,正是这个原因,线程又被称之为 轻量级进程;
**程序:**程序是指包含指令和数据的文件,被存储到磁盘或者其他的数据存储设备中,也就是说程序是静态的代码
进程:进程是程序的一次执行过程,是系统运行程序的基本单位,进程是动态的。系统运行一个程序就是一个进程从创建到运行到死亡的过程。简而言之:一个进程就是一个执行过程中的程序。
10、List,Set,Map三者的区别和实现
List:
-
List接口存储的数据可以有多个重复的对象,有序
-
实现方法:
public class Demo { static List<String> list = new ArrayList<>(); public static void main(String[] args) { //添加 list.add("张三"); list.add("李四"); list.add("王二麻子"); list.add("张三"); System.out.println(list); //根据索引查找 下标从0开始 System.out.println(list.get(1)); //返回list集合的长度; int size = list.size(); //替换 list.set(0,"张二"); System.out.println(list.get(0)); //包含 list.contains("张二"); //判断是否为空 list.isEmpty(); //迭代器:Java Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法,可用于迭代 ArrayList 和 HashSet 等集合。 //Iterator 是 Java 迭代器最简单的实现,ListIterator 是 Collection API 中的接口, 它扩展了 Iterator 接口。 final Iterator<String> iterator = list.iterator(); //删除元素 list.remove(2); } }
Set:
- 不允许有重复的对象,无序
Map:
-
使用键值对的方法存储,双列集合,Key不可重复。
-
实现方法
public class Demo { public static void main(String[] args) { Map<Integer,String> map = new HashMap<>(); Integer a=0; map.put(a+=1,"张三"); map.put(a+=1,"李四"); map.put(a+=1,"王五"); final Collection<String> values = map.values(); //显示内容 System.out.println(values); //显示键值对 System.out.println(map); //根据索引获取 final String s = map.get(0); System.out.println(s); //删除元素 map.remove(1); //删除全部元素 map.clear(); System.out.println(map); } }