java基础总结
一.Object类
public native int hashCode(); //计算的是地址的hashCode
public boolean equals(Obj obj){ //判断两个对象是否相等,比较的是地址,即是否是同一个对象
return (this == obj);
}
public final native void notify()
public final native void notifyAll()
public final native void wait(long timeout)
二.==的作用
比较基本类型时,比较的是两个变量的值是否相等
比较两个引用类型时,比较的是两个对象的地址是否相等。
三.equals
从object类继承的方法,比较的是两个对象的地址
重写equals后,我们可以比较两个对象的内容是不是相等。
重写equals代码:
@Override
public boolean equals(Object obj) {
Student other = (Student) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
四.equals 和 == 有什么区别呢?
在比较两个对象时,== 比较的是两个对象的地址,
如果对象没有重写equals方法,此时比较的是对象的地址,和==功能一样
如果对象重写了equals方法,此时比较的是对象的内容是否相等。
五.hashCode()
方法的作用:计算对象的hash值,
那么当两个元素相等,那么他们的hashCode()一定相等。(计算规则相等)
如果hashCode相等,那么对象不一定相等。(经过复杂的计算得到的结果可能相等)
重写hashCode()代码:
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
六.hashCode()和equals()的关系
类的用途:
1.类不会在HashSet,HashTable,HashMap等这些本质是散列表的数据结构中存储。
那么,该类的hashCode()和equals没有半毛钱关系
equals方法比较对象是否相等。hashCode没有任何作用.
2.类会在HashSet,HashTable,HashMap等这些本质是散列表的数据结构中存储。例如,会创建该类的HashSet集合。
这样,这个类必须重写equals方法和hashCode方法。
如果两个对象相等(通过equals方法比较返回true),hashCode值相等。
如果hashCode相等(代表hash值相等),并不代表两个对象相等,比如hash冲突。
如果hashCode不相等,两个对象肯定不相等。
3.为什么重写了equals方法,还要重写hashCode方法
如果不重写hashCode方法,虽然通过equals比较后,两个对象相同。但HashSet还会有重复的元素。因为这时hashCode是通过对象的地址计算hashCode的,肯定不相同。
=============================================================================================================
static
作用:方便在没有创建对象的情况下进行调用(变量/方法)
1.修饰变量
静态变量被所有对象共享,内存中只有一个副本。会在类加载时初始化
非静态变量在对象创建的时候初始化,有多个副本,每个对象拥有的副本互不影响。
静态变量是可以通过对象访问的,静态方法也是
注意:static是不能修饰局部变量的
2.静态方法
不能访问非静态成员变量,不能访问非静态成员方法。不能用this
3.修饰代码块
可以把初始化的操作放在static代码块中。并且只初始化一次。
static可以出现在类的任何地方,就是不能出现在方法的内部。
static不可以修饰构造方法
=============================================================================================================
abstract和接口:
一.abstract
1.修饰类:这个类成为一个抽象类,那么这个类不能生成对象实例
public abstract class{}
2.修饰方法:方法变成抽象方法,只有声明而没有实现,需要子类继承实现
public abstract void show();
注意:被abstract修饰的类,或有抽象方法的类是抽象类。但是抽象类中不一定都是抽象方法,可以是具体方法
抽象类就是为了继承而存在,如果定义了一个抽象类,却不去继承,那么这个抽象类就白白创建了,不能用它来做任何事。
3.抽象类和普通类的区别:
抽象方法不能用private修饰(无法被子类继承,子类无法实现抽象方法),缺省默认public
抽象类不能用来创建对象
抽象类的子类,必须实现父类的抽象方法。如果没有实现抽象方法,那么子类也是抽象类
二.接口
接口泛指供别人调用的方法,它是对行为的抽象
1.接口中的变量被隐式的指定为public static final变量
2.接口中的方法被隐式的指定为 public abstract
三.区别
抽象类可以有普通方法,接口中只有抽象方法
抽象类可以有普通成员变量,接口中的变量只能是public static final
一个类只能继承一个抽象类,一个类可以实现多个接口
=============================================================================================================
final
一.基本用法:修饰类,方法,变量(包括局部变量和成员变量)。
1.final修饰类,类不能被继承。并且该类中的方法都被隐式的指定为final方法
2.final修饰方法:可以把方法锁定,禁止该方法在子类中被覆盖。即不能被重写
3.修饰变量:fian成员变量表示常量,只能被赋值一次,赋值后值不再改变
4.final修饰引用变量:变量不能再指向其他对象,但是它指向的对象的内容是可变的。
=============================================================================================================传值还是传引用?
都是传值
对于基本数据类型:传递的是值的拷贝
对于引用数据类型:传递的是引用指向的对象的地址值的拷贝
=============================================================================================================内部类:
成员内部类
方法内部类
匿名内部类
静态内部类
=============================================================================================================引用:
1.分类:强引用,软引用,弱引用,虚引用。
2.为什么要引入四种引用类型:
可以通过代码管理对象的生命周期,有利于JVM进行垃圾回收
3.强引用:
Object object = new Object();
String str = "hello";
只要某个对象有强引用与之关联,JVM一定不会回收这个对象。如果内存不足,JVM会抛出OutOfMemory错误
public void fun1() {
Object object = new Object();
Object[] objArr = new Object[1000];//运行这句时,即使内存不足,JVM抛出OOM错误,也不会回收object指向的对象
}
当fun1运行完之后,object和objArr都已经不存在了,所以他们指向的对象都会被JVM回收。
如果想中断强引用和某个对象之间的关联,可以显式的将引用赋值为null,这样JVM会在合适的时间回收改对象
4.软引用:
在Java中用java.lang.ref.SoftReference类来表示,软引用关联着的对象,只有在内存不足时JVM才会回收改对象。可以用来解决OOM问题
SoftReference<String> sr = new SoftReference<String>(new String("hello"));
System.out.println(sr.get());
5.弱引用:
用java.lang.ref.WeakReference类来表示,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象,
WeakReference<String> sr = new WeakReference<String>(new String("hello"));
System.out.println(sr.get());
System.gc(); //通知JVM的gc进行垃圾回收
System.out.println(sr.get()); //打印:null
可以用来解决OOM问题。
=============================================================================================================
内存溢出:
1.内存泄露:申请者使用完的内存没有释放,导致虚拟机不能再次使用该内存,这段内存就泄露了
2.内存溢出:申请的内存超出了JVM能提供的内存大小
最常见的OOM情况有以下三种:
java.lang.OutOfMemoryError: Java heap space ------>java堆内存溢出,此种情况最常见,一般由于内存泄露或者堆的大小设置不当引起。对于内存泄露,需要通过内存监控软件查找程序中的泄露代码,而堆大小可以通过虚拟机参数-Xms,-Xmx等修改。
java.lang.OutOfMemoryError: PermGen space ------>方法区溢出,一般出现于大量Class或者采用cglib等反射机制的情况,因为上述情况会产生大量的Class信息存储于方法区。此种情况可以通过更改方法区的大小来解决,使用类似-XX:PermSize=64m -XX:MaxPermSize=256m的形式修改。另外,过多的常量尤其是字符串也会导致方法区溢出。
java.lang.StackOverflowError ------>?不会抛OOM error,但也是比较常见的Java内存溢出。JAVA虚拟机栈溢出,一般是由于程序中存在死循环或者深度递归调用造成的,栈大小设置太小也会出现此种溢出。可以通过虚拟机参数-Xss来设置栈的大小。