初级Java开发工程师!绝密文档,面试手册全面突击!!!秋招已经到来
这里我要明说一下,不是Java初级和学习Java的千万不要乱看,否则~~~~
你会怀疑人生,因为会浪费你时间啊!!!
本次考点是Java初级开发工程师面试必备的一些东西!!!
1、数据类型
基本类型
byte/8、short/16、int/32、long/64、boolean/ 、char/16、float/32、double/64
boolean
只有两个值,true
、false
,可以使用1bit
来存储,但是具体大小没有明确规定,JVM
会在编译时期将boolean
类型转为int,使用1来表示true
,0表示false
。JVM
支持boolean
数组,但是是通过读写byte
数组来实现的。> 获取资料的方式:JAVA架构速成笔记
包装类型
基本类型都有对应的包装类型,基本类型与其对应的包装类型之间的赋值使用自动装箱与拆箱完成。
Integer x=2 //装箱,调用了Integer.valueOf(2)
int y=x //拆箱 调用了 X.intValue()
缓存池
new Integer(123)与Integer.valueOf(123)的区别在于:
new Integer(123)每次都会新建一个对象
Integer.valueOf(123)会使用缓存池中的对象,多次调用会取得同一对象的引用。
Integer x = new Integer(123);
Integer y = new Integer(123);
System.out.println(x == y); // false
Integer z = Integer.valueOf(123);
Integer k = Integer.valueOf(123);
System.out.println(z == k); // true
valueOf()
方法的实现比较简单,就是先判断值是否在缓存池中,如果在的话就直接返回缓存池的内容。
2、String
概览
String被声明为final,因此它不可被继承。(Integer
等包装类也不能被继承)
在java8中,String 内部使用char数组存储数据。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
在java9之后,String类的实现改用byte数组存储字符串,同时使用coder
来标识使用了那种编码。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte[] value;
/** The identifier of the encoding used to encode the bytes in {@code value}. */
private final byte coder;
}
value 数组被声明为 final
,这意味着value
数组初始化之后就不能再引用其它数组。并且 String 内部没有改变 value 数组的方法,因此可以保证 String
不可变。
不可变的好处
1、可以缓存hash值
因为String的hash值经常被使用,例如String用作HashMap
的key。不可变的特性可以使得hash值也不可变,因此只需要进行一次计算。
2、String Pool的需要
字符串常量池,如果一个String
对象已经被创建过了,那么会从String Pool
中取得引用。只有String是不可变的,才可能使用String Pool
。
3、安全性
String
经常作为参数,String不可变性可以保证参数不可变。
4、线程安全
String
不可变性天生具备线程安全,可以在多个线程中安全地使用。
String Pool
字符串常量池(String Pool)
保存这所有字符串字面量,这些字面量在编译时期就确定。不仅如此,还可以使用String
的intern()
方法在运行过程中将字符串添加到String Pool中。
Pool中已经存在一个字符串和该字符串值相等(使用
equals方法进行确定),那么就会返回
String Pool中字符串的引用;否则,就会在
String Pool`中添加一个新的字符串,并返回这个新字符串的引用。> 获取资料的方式:JAVA架构速成笔记
下面实例:s1
和s2
采用new String()
的方式新建了两个不同字符串,而s3和s4是通过s1.intern()
和s2.intern()
方法取得同一个字符串引用。intern()
首先把“aaa”放到String Pool
中,然后返回这个字符串的引用,因此s3和s4引用的是同一字符串。
String s1 = new String("aaa");
String s2 = new String("aaa");
System.out.println(s1 == s2); // false
String s3 = s1.intern();
String s4 = s2.intern();//加入Java开发交流君样:756584822一起吹水聊天
System.out.println(s3 == s4); // true
如果采用"bbb"这种字面量的形式创建字符串,会自动地将字符串放入String Pool中。
String s5 = "bbb";
String s6 = "bbb";
System.out.println(s5 == s6); // true
new String("abc")
问题,使用这种方式一共会常见两个字符串对象(前提是String Pool
中还没有"abc"字符串对象)
abc属于字符串字面量,因此编译时期会在String Pool
中创建一个字符串对象,指向这个"abc"字符串字面量 而使用new的方式会在堆中创建一个字符串对象。
3、运算
参数传递
java
的参数是以值传递的形式传入方法中,而不是引用传递。
在给方法传入参数时候,如果传入对象,对象名其实代表地址,即将对象的地址传给该方法。在运行时候可以对对象进行改变。
在方法中改变对象的字段值会改变原对象该字段值,因为引用的是同一个对象。
float与double
java不能隐式执行向下转型,因为这会使得精度降低
字面量属于double类型,不能直接将1.1直接赋值给float变量,因为这是向下转型。
float f=1.1 //这会编译错误
1.1f字面量才是float类型
//加入Java开发交流君样:756584822一起吹水聊天
float f=1.1f
隐士类型转换
因为字面量1是int类型,它比short类型精度要高,因此不能隐式地将int类型向下转型为short类型
4、关键字
final
1、数据
声明数据为常量,可以是编译时常量,也可以是在运行时被初始化后不能被改变的常量。
对于基本类型,final使数据不变
对于引用类型,final使引用不变,也就不能引用其他对象,但是被引用的对象本身是可以修改的。
final int x = 1;
// x = 2; //不能赋值给被final修饰的变量
final A y = new A();
y.a = 1;
2、方法
声明方法不能被子类重写。
private方法隐式地被指定为final,如果在子类中定义的方法和基类中的一个private方法签名相同,此时子类的方法不是重写基类方法,而是在子类中定义了一个新的方法。
3、类
声明类不允许被继承。
static
1、静态变量
静态变量:又被称为类变量,也就是说这个变量属于类的,类所有的实例都共享静态变量,可以直接通过类名来访问它。静态变量在内存中只存在一份。> 获取资料的方式:JAVA架构速成笔记
实例变量:没创建一个实例就会产生一个实例变量,它与实例同生共死。
public class A {
private int x; // 实例变量
private static int y; // 静态变量
public static void main(String[] args) {
// int x = A.x; // Non-static field 'x' cannot be referenced from a static context
A a = new A();
int x = a.x;
int y = A.y;
}
}//加入Java开发交流君样:756584822一起吹水聊天
2、静态方法
- 静态方法在类加载的时候就存在了,它不依赖于任何实例。所有静态方法必须有实现,也就是说它不能是抽象方法。
- 静态方法只能访问所属类的静态字段和静态方法,方法中不能有this和super关键字,因此这两个关键字与具体对象关联。
3、静态语句块
静态语句块在类初始化时运行一次
public class A {
static {
System.out.println("123");
}
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
}
}
123 4、静态内部类
非静态内部类依赖于外部类的实例,也就是说需要先创建外部实例,才能用这个实例去创建非静态内部类。而静态内部类不需要。
5、初始化顺序
静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。
public static String staticField = "静态变量";
static {
System.out.println("静态语句块");
}
public String field = "实例变量";
{//加入Java开发交流君样:756584822一起吹水聊天
System.out.println("普通语句块");
}
最后才是构造函数的初始化
public InitialOrderTest() {
System.out.println("构造函数");
}
存在继承的情况下,初始化顺序为:
父类(静态变量、静态语句块)
子类(静态变量、静态语句块)
父类(实例变量、普通语句块)
父类(构造函数)
子类(实例变量、普通语句块)
子类(构造函数)
5、继承
访问权限
Java中有三个访问权限修饰符:private
、protected
以及public
,如果不加访问修饰符,表示包级可见。
可以对类或类中的成员(字段和方法)加上访问修饰符。
- 类可见表示其它类可以用这个类创建实例对象
- 成员可见表示其它类可以用这个类的实例对象访问到改成员;
protected
用于修饰成员,表示在继承体系中成员对于子类可见,但是这个访问修饰符对于类没有意义。
如果子类的方法重写了父类的方法,那么子类中该方法的访问级别不允许低于父类的访问级别。这是为了确保可以使用父类实例的地方都可以使用子类实例去代替,也就是确保满足里式替换原则。> 获取资料的方式:JAVA架构速成笔记
字段决不能是共有的,因为这么做的话就市区了对这个字段修改行为的控制,客户端可以对其随意修改。我们可以使用公有的getter
和setter
方法来替换公有字段,这样的话可以控制对字段的修改行为。
抽象类与接口
1、抽象类
抽象类和抽象方法都使用abstract关键字进行声明。如果一个类中包含抽象方法,那么这个类必须声明为抽象类。
抽象类和普通类最大的区别是,抽象类不能被实例化,只能被继承。
public abstract class AbstractClassExample {
protected int x;
private int y;
public abstract void func1();
public void func2() {
System.out.println("func2");
}
}
public class AbstractExtendClassExample extends AbstractClassExample {
@Override
public void func1() {
System.out.println("func1");
}
}//加入Java开发交流君样:756584822一起吹水聊天
// AbstractClassExample ac1 = new AbstractClassExample(); // 'AbstractClassExample' is abstract; cannot be instantiated
AbstractClassExample ac2 = new AbstractExtendClassExample();
ac2.func1();
2、接口
接口是抽象类的延伸,在java8之前,他可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。
从java8开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口维护成本太高了。 在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。
接口的成员(字段 + 方法)默认都是 public
的,并且不允许定义为 private 或者 protected
。从 Java 9 开始,允许将方法定义为 private
,这样就能定义某些复用的代码又不会把方法暴露出去。
接口的字段默认都是 static
和final
的。
重写与重载
1、重写
存在于继承体系中,指子类实现了一个与父类在方法声明上完全相同的一个方法。
为了满足里式替换原则,重写有一下三个限制:
-
子类方法的访问权限必须大于等于父类方法
-
子类方法的返回类型必须是父类方法返回类型或为其子类型
-
子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型
2、重载
存在于同一个类中,指一个方法与已经存在的方法名称上相同,但是参数类型、个数、顺序至少有一个不同。
应该注意的是,返回值不同,其它都相同不算是重载。
反射
每一个类都有一个Class对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名 的.class文件,该文件内容保存着Class对象。
类加载相当于Class对象的加载,类在第一次使用时才动态加载到JVM中。也可以使用Class.forName("com.mysql.jdbc.Driver")
这种方式来控制类的加载,该方法会返回一个Class对象。
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的.class不存在也可以加载进来。
Class
和java.lang.reflect
一起对反射提供了支持,java.lang.reflect
类库主要包含了以下三个类:
-
Field
:可以使用get()和set()方法读取和修改Field对象关联的字段 -
Method
:可以使用invoke()方法调用与Method
对象关联的方法 -
Constructor
:可以用Constructor和newInstance()
创建新的对象
反射的优点:
- 可扩展性:应用程序可以利用全限定类名创建可扩展对象的实例,来使用来自外部的用户自定义类。
- 类浏览器和可视化开发环境:一个类浏览器需要可以枚举类的成员。可视化开发环境(如IDE)可以从反射中可用的类型信息中收益,帮助程序员编写正确的代码。
- 调试器和测试工具:调试器需要能够检查一个类里的私有成员。测试工具可以利用反射来自动地调用类里定义的可被发现的API定义,以确保一组测试中有较高的代码覆盖率
反射的缺点:
尽管反射很强大,但是不能滥用。如果一个功能可以不用反射完成,那么最好不用。
最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰。
可以的话请给我一个三连支持一下我哟> 获取资料的方式:JAVA架构速成笔记