记录学习Java过程中的一些小知识点
空指针访问静态变量时不会引发空指针异常
静态方法必须使用“类名.方法名”,而静态变量既可以使用"类名.变量名" 也可以使用"对象名.变量名"。实际上我们在使用对象名.变量名来操作静态变量时,实际上,JVM会将其解释为类名.变量名,这意味着下面这种情况不会发生空指针异常。
public class Demo {
public int id;
public String name;
public static String country="中国";
public static void main(String[] args) {
Demo test = new Demo();
test = null;
System.out.println(test.country);
}
}
输出结果为

结论:只有在”空引用“ 访问”实例“相关的,才会发生空指针异常
实例代码块、静态代码块、构造函数的执行顺序
当new一个对象时候。
静态代码块先执行,之后是实例代码块,最后是构造函数
静态代码块可以用来统计对象的数量、初始化静态成员变量等。
实例代码块在开发中作用不大
this的内存结构
一个this一个对象
this是一个引用,保存当前对象的内存地址,指向自身。
this存储在堆内存当中对象的内部

this只能使用在实例方法中
this不能省略的情况
在setter,形参的名字最好与成员变量的相同,但是这样的话在赋值的时候,成员变量必须加this.修饰,因为不加this.修饰的话,setter中的变量都将是形参(按照就近原则) 赋值操作就变成了形参给形参自己赋值
例如
public class Demo{
private int a;
public void setA(int a){
a=a; //这里就变成形参a=形参a了
}
}
this还可用在构造方法中
通过当前的构造方法去调用另一个本类的构造方法,可以使用以下的语法格式:this(实际参数列表);
注意事项:对this的调用必须是构造器中的第一个语句(java就是这么规定的)
super
- super能出现在实例方法和构造方法中
- super的语法是:”super.“和”super()“
- super.可以访问父中的非私有 属性和方法
- super不能使用在静态方法中
- super.大部分情况下是可以省略的,当父类和子类中有同名属性或者方法,若要在子类中访问父类的属性或者和方法则需要加super.限定
- super()只能出现在构造方法的第一行,通过当前构造方法调用父类的构造方法,目的是创建子类时,先初始化父类型特征。
- super()和this()不能共存
在子类的构造函数中没有this和super,java会默认添加一个super()表示通过当前子类的构造方法调用父类的无参构造函数,所以必须保证父类的无参构造函数时存在的
super不是引用,也不保存内存地址,也不指向任何对象,只是代表当前对象内部的那一块父类型的特征。
因此输出super不能输出形如”类名@地址的字符串“
public void doSome(){
System.out.println(this);
System.out.println(super); //报错
}
为什么this、super不能出现在静态方法中?
因为静态方法是通过类名引用的,调用非静态方法时,this指向当前对象,super是当前对象的父类特征部分。而调用非静态方法是通过类名调用的,就不存在当前对象了this无引用的对象了,因此java不允许这样做。
Object类中的toString方法
该方法时返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。
Object 类的 toString 方法返回一个字符串,它的值等于:
getClass().getName() + '@' + Integer.toHexString(hashCode())
hashCode()是Object类的一个方法,返回该对象的哈希值。
哈希值是通过哈希算法计算出来的一个地址值(并非实际地址值)。
当我们直接用System.out.println()直接输出一个对象名的时候,会自动的调用该对象的toString方法,输出一个“类名@地址值”的字符串
验证
public class Demo {
public int id;
public String name;
public static String country="中国";
{
System.out.println();
}
public static void main(String[] args) {
Demo test = new Demo();
System.out.println("test = "+test);
System.out.println("test.toString() = "+test.toString());
}
}
输出结果为

我们可以手动重写这个方法,来实现直接用println输出对象的内容
匿名内部类
匿名内部类可以使你的代码更加简洁,你可以在定义一个类的同时对其进行实例化。它与局部类很相似,不同的是它没有类名,如果某个局部类你只需要用一次,那么你就可以使用匿名内部类。
下面是官方文档里匿名内部类的用法
public class HelloWorldAnonymousClasses {
/**
* 包含两个方法的HelloWorld接口
*/
interface HelloWorld {
public void greet();
public void greetSomeone(String someone);
}
public void sayHello() {
// 1、局部类EnglishGreeting实现了HelloWorld接口
class EnglishGreeting implements HelloWorld {
String name = "world";
public void greet() {
greetSomeone("world");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hello " + name);
}
}
HelloWorld englishGreeting = new EnglishGreeting();
// 2、匿名类实现HelloWorld接口
HelloWorld frenchGreeting = new HelloWorld() {
String name = "tout le monde";
public void greet() {
greetSomeone("tout le monde");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Salut " + name);
}
};
// 3、匿名类实现HelloWorld接口
HelloWorld spanishGreeting = new HelloWorld() {
String name = "mundo";
public void greet() {
greetSomeone("mundo");
}
public void greetSomeone(String someone) {
name = someone;
System.out.println("Hola, " + name);
}
};
englishGreeting.greet();
frenchGreeting.greetSomeone("Fred");
spanishGreeting.greet();
}
public static void main(String... args) {
HelloWorldAnonymousClasses myApp = new HelloWorldAnonymousClasses();
myApp.sayHello();
}
}
静态数组作为方法参数
必须这么写: 方法名(new int[]{1,2,3,4});
数组拷贝
只能再建一个更大的数组,将满了的数组里的元素拷贝进去。
可以使用System.arraycopy()方法
System.arraycopy
public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
作用:将指定源数组中的数组从指定位置复制到目标数组的指定位置。
参数:
src - 源数组。
srcPos - 源数组中的起始位置。
dest - 目标数组。
destPos - 目的地数据中的起始位置。
length - 要复制的源数组元素的数量。
举例:
原数组:int[] arr={1,2,3,4,5,6,7,8,9,0};
目标数组:int[] Arr=new int[4];
操作:将原数组第二个位置以后的4个数据copy到目标数组
System.arrayCopy(arr,1,Arr,0,4);
除此之外,Array.copyOf也可以用来拷贝数组
Arrays.copyOf()不仅仅只是拷贝数组中的元素,在拷贝元素时,会创建一个新的数组对象。而System.arrayCopy只拷贝已经存在数组元素。
其实Array.copyOf底层使用System.arrayCopy实现的,下面是源代码
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
Arrays类
Java的Arrays类中有一个sort()方法,该方法是Arrays类的静态方法,在需要对数组进行排序时,非常的好用。
但是sort()的参数有好几种,下面我就为大家一一介绍,这几种形式的用法。
1、Arrays.sort(int[] a)
这种形式是对一个数组的所有元素进行排序,并且是按从小到大的顺序。
2、Arrays.sort(int[] a, int fromIndex, int toIndex)
这种形式是对数组部分排序,也就是对数组a的下标从fromIndex到toIndex-1的元素排序,注意:下标为toIndex的元素不参与排序哦!
3、public static void sort(T[] a,int fromIndex,int toIndex, Comparator c)
上面有一个拘束,就是排列顺序只能是从小到大,如果我们要从大到小,就要使用这种方式
1 package test;
2
3 import java.util.Arrays;
4 import java.util.Comparator;
5
6 public class Main {
7 public static void main(String[] args) {
8 //注意,要想改变默认的排列顺序,不能使用基本类型(int,double, char)
9 //而要使用它们对应的类
10 Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
11 //定义一个自定义类MyComparator的对象
12 Comparator cmp = new MyComparator();
13 Arrays.sort(a, cmp);
14 for(int i = 0; i < a.length; i ++) {
15 System.out.print(a[i] + " ");
16 }
17 }
18 }
19 //Comparator是一个接口,所以这里我们自己定义的类MyComparator要implents该接口
20 //而不是extends Comparator
21 class MyComparator implements Comparator<Integer>{
22 @Override
23 public int compare(Integer o1, Integer o2) {
24 //如果n1小于n2,我们就返回正值,如果n1大于n2我们就返回负值,
25 //这样颠倒一下,就可以实现反向排序了
26 if(o1 < o2) {
27 return 1;
28 }else if(o1 > o2) {
29 return -1;
30 }else {
31 return 0;
32 }
33 }
34
35 }
二分查找
Arrays.binarySearch(int arr[],int key)
finally子句
在异常处理机制中,finally子句总会执行。
即使前面有return也会执行

但是如果退出虚拟机的话,finally就不执行了

面试题,求输出的result为几?
public class test{
public static void main(String[] args) {
int result = m();
System.out.println(result);
public static int m(){
int i =100;
try {
return i;
}finally {
i++;
}
}
}
}
答案是100。为什么是100而不是101呢?不是说先执行try,在执行finally,最后在执行return吗?实际上确实是这样的,之所以输出100是因为java中有一些规则是不能破坏的,一旦这么说了就必须这么做!
java中有这么一条规则:方法体中的代码必须遵循自上而下顺序依次逐行执行。
就是说,即使实际上是按照try、finally、return顺序执行的,但是程序返回的的结果是按自上而下的顺序执行出的结果。
下面看一下反编译后的代码

final finally finalize有什么区别
final是一个关键字,表示最终的、不可变的
finally也是一个关键字,和try联合使用,表示一定会执行
finalize是一个方法,Object类中的方法,一个对象被垃圾回收时会执行它的finalize方法
6466

被折叠的 条评论
为什么被折叠?



