java基础知识复习

JAVA 基础知识复习

“==”equals()的区别:

  1. 基础数据类型使用"=="比较的是它们的值
  2. 引用数据类型使用"=="比较的是它们是否是在同一片内存(只有同一个new出来的对象是相等的,否则都是不等的,因为每一次new都会重新开辟新的堆内存
  3. equals()原始和==一样,但是大多数库将这个方法复写,复写之后一般是用来比较成员变量的值是否相等

Java 反射 & 类加载

动态反射:

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 在运行时调用任意一个对象的方法

反射运用

1 获得Class对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 使用Class类的forName静态方法
*/
public static Class<?> forName(String className)
//比如在 JDBC 开发中常用此方法加载数据库驱动:
Class.forName(driver);

/**
* 直接获取某个对象的class
*/
Class<?> clazz = int.class;
Class<?> classInt = Integer.TYPE;
/**
* 调用某个对象的getclass方法
*/
StringBuilder str = new StringBuilder("123");
Class<?> clazz = str.getClass();

2 判断是否是某个类的实例

使用instanceof判断,也可以接触反射中Class对象的isInstance()方法来判断是否是某个类的实例

1
public native boolean isInstance(Object obj)

3 创建实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 使用Class对象的newInstance()方法来创建Class对象对应类的实例。
*/
Class<?> c = String.class;
Object str = c.newInstance();
/**
* 通过Class对象获取指定的Constructor对象
* 再调用Constructor对象的newInstance()方法来创建实例。
*/
//获取String所对应的Class对象
Class<?> c = String.class;
//获取String类带一个String参数的构造器
Constructor constructor = c.getConstructor(String.class);
//根据构造器创建实例
Object obj = constructor.newInstance("23333");
System.out.println(obj);

4 获取方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class test1 {
public static void test() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class<?> c = methodClass.class;
Object object = c.newInstance();
Method[] methods = c.getMethods();
/** declaredMethods
* 返回类或接口声明的所有方法,
* 包括公共、保护、默认(包)访问和私有方法
* 但不包括继承的方法。
*/
Method[] declaredMethods = c.getDeclaredMethods();
/** getMethod
* 返回一个特定的方法
* 其中第一个参数为方法名称
* 后面的参数为方法的参数对应Class的对象。
*/
Method method = c.getMethod("add", int.class, int.class);
/** getMethods()
* 方法获取的所有public方法
*/
System.out.println("getMethods获取的方法:");
for(Method m:methods)
System.out.println(m);
//getDeclaredMethods()方法获取的所有方法
System.out.println("getDeclaredMethods获取的方法:");
for(Method m:declaredMethods)
System.out.println(m);
}
}
class methodClass {
public final int fuck = 3;
public int add(int a,int b) {
return a+b;
}
public int sub(int a,int b) {
return a+b;
}
}

5 获取构造器信息

1
public T newInstance(Object ... initargs)

6 获取类的成员变量信息

1
2
3
4
getFiled();//访问公有的成员变量
getDeclareField();//所有已声明的成员变量,但不能得到其父类的成员变量
getFileds();
getDeclaredFields();

7 调用方法

从类中获取了一个方法后,我们就可以用 invoke() 方法来调用这个方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public Object invoke(Object obj, Object... args) throws 
IllegalAccessException, IllegalArgumentException, InvocationTargetException

public class test1 {
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
Class<?> klass = methodClass.class;
//创建methodClass的实例
Object obj = klass.newInstance();
//获取methodClass类的add方法
Method method = klass.getMethod("add",int.class,int.class);
//调用method对应的方法 => add(1,4)
Object result = method.invoke(obj,1,4);
System.out.println(result);
}
}
class methodClass {
public final int fuck = 3;
public int add(int a,int b) {
return a+b;
}
public int sub(int a,int b) {
return a+b;
}
}

其他

动态代理与静态代理的区别

生成的时间不同,如果需要对多个类进行代理且代理的功能相同,可以使用动态代理生成代理类

类加载

过程

1
2
3
4
5
6
7
8
9
10
11
Person person = new Person();
/**
* 1 查找Person.class,并加载到内存中
* 2 执行类里的静态代码块。
* 3 在堆内存里开辟内存空间,并分配内存地址。
* 4 在堆内存里建立对象的属性,并进行默认的初始化。
* 5 对属性进行显示初始化。
* 6 对对象进行构造代码块初始化。
* 7 调用对象的构造函数进行初始化。
* 8 将对象的地址赋值给person变量。
**

双亲委派机制

类的加载首先会调用父类的加载器,只有当父类无法加载的时候,才会用子类的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public abstract class ClassLoader {

protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
//首先,检查该类是否已经被加载
Class c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
//先调用父类加载器去加载
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}

if (c == null) {
//如果父类加载器没有加载到该类,则自己去执行加载
long t1 = System.nanoTime();
c = findClass(name);

// this is the defining class loader; record the stats
}
}
return c;
}
}