Java 基础
Java基础
Java的四种引用方式
因为值类型存储于Stack里,引用类型存储于Heap里,但是在Stack里有指向Heap的引用。
Java简单数据类型没有String。
简单数据类型具有栈共享。
int a = 3;int b = 3;
那么a和都储存在 栈里且指向同一个字面值3。但是对a,b的分别修改是不会导致对方数值的变化。
Java的简单数据类型作为参数时传递的是值(Pass by Value),在函数中使用的是源变量的拷贝,对源变量不产生影响。
引用是一种数据类型(保存在stack),保存了对象在内存(heap)中的地址,这种类型即不是我们平时所说的简单数据类型也不是类实例(对象)。
强引用(StrongReference)
是指创建一个对象并把这个对象赋给一个引用变量。
比如:
Object object = new Object();
String str = "hello";
软引用(SoftReference)
1 | //创建对象强引用 |
弱引用(WeakReference)
1 | //用java.lang.ref.WeakReference类来表示。 |
虚引用(PhantomReference)
1 | //用java.lang.ref.PhantomReference类来表示。 |
垃圾回收顺序为 虚引用—>弱引用—>软引用—>强引用。
弱引用在没有强引用被执行gc时马上回收。软引用在没有强引用且内存不足被执行gc时回收。
Java的垃圾回收机制
垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存。
内存泄露是指该内存空间使用完毕之后未回收,在不涉及复杂数据结构的一般情况下,Java 的内存泄露表现为一个内存对象的生命周期超出了程序需要它的时间长度,我们有时也将其称为对象游离。
Java的类反射机制
.getClass( ) .class Class.forName( )
1 | public static void main(String[] args) { |
Class.forName( )对比
Class.forName( )和ClassLoader.loadClass( )的区别:
Class.forName( )默认初始化执行static方法。
类反射代码详解
1 | //类加载 |
Java重要关键字
访问控制
1 | * 成员变量/方法的访问权限 |
private
只能在声明 private(内部)类、方法或字段的类中引用这些类、方法或字段。在类的外部或者对于子类而言,它们是不可见的。 所有类成员的默认访问范围都是 package 访问,也就是说,除非存在特定的访问控制修饰符,否则,可以从同一个包中的任何类访问类成员。
protected
可以在声明 protected 类、方法或字段的类、同一个包中的其他任何类以及任何子类(无论子类是在哪个包中声明的)中引用这些类、方法或字段。所有类成员的默认访问范围都是 package 访问,也就是说,除非存在特定的访问控制修饰符,否则,可以从同一个包中的任何类访问类成员。
public
可能只会在其他任何类或包中引用 public 类、方法或字段。所有类成员的默认访问范围都是 package 访问,也就是说,除非存在特定的访问控制修饰符,否则,可以从同一个包中的任何类访问类成员。
类 方法 变量修饰符
abstract
- 不能直接实例化。
- 方法不在声明它的类中实现,但必须在某个子类中重写。
- 采用 abstract 方法的类是抽象类,必须声明为abstract。
class
- 用来声明新的类,该类是相关变量和/或方法的集合。
- 类是对象的模板,每个对象都是类的一个实例。
- 要使用类,通常使用 new 操作符将类的对象实例化,然后调用类的方法来访问类的功能。
extends
- 用在 class 或 interface 声明中,用于指示所声明的类或接口是子类。
- 子类继承父类的所有 public 和 protected 变量和方法。
- 子类可以重写父类的任何非 final 方法。
final
- 可以应用于类,以指示不能扩展该类(不能有子类)。
- final 关键字可以应用于方法,以指示在子类中不能重写此方法。
- 一个类不能同时是 abstract 又是 final。abstract 意味着必须扩展类,final 意味着不能扩展类。abstract 意味着必须重写方法,final 意味着不能重写方法。
implements
- 在 class 声明中使用,以指示所声明的类提供了指定的接口中所声明的所有方法的实现。
- 类必须提供在接口中所声明的所有方法的实现。
- 一个类可以实现多个接口。
interface
- 用来声明新的 Java 接口,接口是方法的集合。
- 接口是 Java 语言的一项强大功能。任何类都可声明它实现一个或多个接口,这意味着它实现了在这些接口中所定义的所有方法。
- 实现了接口的任何类都必须提供在该接口中的所有方法的实现。一个类可以实现多个接口。
native
- 可以应用于方法,以指示该方法是用 Java 以外的语言实现的。
static
- static 关键字可以应用于内部类(在另一个类中定义的类)、方法或字段(类的成员变量)。
- 意味着应用它的实体在声明该实体的类的任何特定实例外部可用。
- static 字段(类的成员变量)在类的所有实例中只存在一次。
- 可以从类的外部调用 static 方法,而不用首先实例化该类。
- 这样的引用始终包括类名作为方法调用的限定符。
strictfp
- 使用它来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果想让浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。
- 可以将一个类、接口以及方法声明为strictfp,但是不允许对接口中的方法以及构造函数声明strictfp关键字。
synchronized
- 可以应用于方法或语句块,并为一次只应由一个线程执行的关键代码段提供保护。
- 可防止代码的关键代码段一次被多个线程执行。
- 如果应用于静态方法,那么,当该方法一次由一个线程执行时,整个类将被锁定。
- 如果应用于实例方法,那么,当该方法一次由一个线程访问时,该实例将被锁定。
- 如果应用于对象或数组,当关联的代码块一次由一个线程执行时,对象或数组将被锁定。
变量引用
super
- 用于引用使用该关键字的类的超类。
- 作为独立语句出现表示调用超类的构造方法。
this
- 当引用可能不明确时,可以使用它来引用当前的实例。
void
- void 关键字表示 null 类型。
- void 可以用作方法的返回类型,以指示该方法不返回值。
保留字
goto
- 保留关键字,但无任何作用。
const
- 类型修饰符,使用它声明的对象不能更新。
Java.IO
java.io.File
File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
public File(String parent,String child)
以parent为父路径,child为子路径创建File对象。
流的分类
(抽象基类) | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
1 | InputStream: |
文件流
读取文件
1 | //建立一个流对象,将已存在的一个文件加载进流。 |
写入文件
1 | //创建流对象,建立数据存放文件 |
缓冲流
对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中的数据立刻写出。
1 | BufferedReader br = null; |
转换流
public InputSreamReader(InputStream in,String charsetName);
字节数组解码成字符串。
public OutputStreamWriter(OutputStream out,String charsetName);
字符串编码成字节数组。
标准输入输出流
System.in的类型是InputStream。
System.out的类型是PrintStream,其是OutputStream的子类FilterOutputStream 的子类。
1 | System.out.println("请输入信息(退出输入e或exit):"); |
对象流
序列化
- 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
- 序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
- 序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础
- 如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
- Serializable
- Externalizable
- 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
- private static final long serialVersionUID;
- serialVersionUID用来表明类的不同版本间的兼容性
- 如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。故建议,显示声明
- 显示定义serialVersionUID的用途
- 希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID
- 不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID
1 | //序列化对象韩梅梅。 |
Java 集合类
1 | Collection |
Java 锁
乐观锁
- 在更新的时候会判断一下在此期间别人有没有去更新这个数据。
- 适用于多读的应用类型,这样可以提高吞吐量。
- 乐观锁的实现方式CAS、数据版本。
- CAS(Compare and Swap 比较并交换)CAS操作中包含三个操作数——内存数据(V)、预期原值(A)、拟写入值(B)。如果V == A,那么更新V为新值B,否则不做任何操作。
悲观锁
- 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁。
- 在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking)。
- 如果成功加锁,那么就可以对记录做修改,事务完成后就会解锁了。
公平锁/非公平锁
- 公平锁是指多个线程按照申请锁的顺序来获取锁。
- 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。
偏向锁/轻量级锁/重量级锁
- 针对Synchronized。
- 偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
- 轻量级锁是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
- 重量级锁是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让他申请的线程进入阻塞,性能降低。
Synchronized
- 可重入锁。
- 非公平锁。
- 悲观锁 。
- 排他锁。
ReenTrantLock
- 可重入锁 。
- 可设置为公平锁。
- 排他锁。