跨平台:Java文件编译后是class文件,class文件符合Java虚拟机规范,每个平台都有一套JVM,class依赖与JVM而不是操作系统
区别:基本数据类型存储在栈中;引用类型数据存储在堆中,对象的引用存储在栈中
Java方法的传参——传值(不论是基本类型还是引用类型);传入的都是引用的副本(这里引用并不是一个地址,而是存储在栈中的值),如果方法中将参数指向另一个对象不会影响实参,但对于引用类型,对参数指向的对象进行修改会影响实参
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Integer a = new Integer(10);
Integer b = new Integer(20);
swap(a,b);
System.out.println(a);
System.out.println(b);
}
public static void swap(Integer a,Integer b) throws NoSuchFieldException, IllegalAccessException {
Class c = Integer.class;
Field field = c.getDeclaredField("value");
//设置可访问性,成败就在这里,由于value字段是private final,只有这一步设置才可以在外部改变他的值
field.setAccessible(true);
int numA = (int) field.get(a);
field.set(a,field.get(b));
field.set(b,numA);
}
每一个基本数据类型都对应有一个包装类:Byte、Short、Integer、Long、Float、Double、Character、Boolean
自动装箱与拆箱
int i = new Integer(100)
:拆箱
Integer i = 100
:装箱
体现:方法传参、泛型集合
Integer的比较
Integer内部有缓冲区默认范围是-128~127,在范围内的数据都存储在常量池中,创建相同数据时会将同一个值返回;超过这个范围会在堆中创建一个Integer对象,两个相同大小的值对应着两个相同的对象,但在堆中的地址不同;而==对于引用类型比较的是地址
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1==i2);//true
Integer i1 = 128;
Integer i2 = 128;
System.out.println(i1==i2);//false
7/2?1:0.9
结果为1.0而不是1&运算的是boolean和数字,&&运算的是boolean
&没有短路,&&会短路
==与equals的区别
equals如果没有Override,默认实现就是==
==可以操作基本类型和引用类型;equals只有引用类型有
import static.package.class.method
可以将方法进行静态导入,在使用时可以不用写类名直接使用方法,method可以使用通配符*表示当前实例,不能用于静态代码块和静态方法
this()访问本类的其他重载形式的构造方法
表示父类的实例,使用super.来访问父类的属性或方法;super()在子类的构造方法中访问父类的构造方法
Java中不能多继承但能多实现(即一个类不能同时继承多个类,但是能同时实现多个接口),因为如果多个类有相同的方法,在子类调用父类方法时会有歧义,而接口对方法没有实现,需要子类进行实现所以没有歧义,在多实现时对于接口中重名的默认方法,子类必须重写该方法
父类静态代码块——》子类静态代码块——》父类变量——》父类代码块——》父类构造方法——》子类变量——》子类代码块——》子类构造方法
保证所有用到该类的实例的地方用到的都是同一个实例
public class Singleton{
//防止外部调用构造方法来构造实例
private Singleton(){}
//在类加载时进行实例化
private static Singleton sinleton = new Sinleton();
//获取实例化的对象
public static Singleton getInstance(){
return sinleton;
}
}
该方式时线程安全的,但是如果有其他静态成员,可能不需要实例化时却实例化了,浪费资源
2. 懒汉式(线程不安全)
public class Sinleton{
private Sinleton(){}
private static Sinleton sinleton = null;
public static Sinleton getInstance(){
if(sinleton == null){
sinleton = new Sinleton();
}
return sinleton;
}
}
该方法只有在需要使用这个实例时实例化,但是存在线程安全问题
3. 懒汉式(线程安全,使用synchronized关键字)
public class Sinleton{
private Sinleton(){}
private static Sinleton sinleton = null;
public static synchronized Sinleton getInstance(){
if(sinleton == null){
sinleton = new Sinleton();
}
return sinleton;
}
}
public class Singleton {
private Singleton () {}
//利用静态内部类创建实例来保证实例只创建一次
private static class SingletonHolder{
private static final Singleton singleton= new Singleton();
}
public static final Singleton getInstance () {
return SingletonHolder.singleton;
}
}
面向对象三大特性:封装,继承,多态
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(test());
}
public static int test(){
try{
int i = 1/1;
return 1;
}catch (Exception e){
return 0;
}finally {
return -1;
}
}
输出结果为-1而不是1
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(test());
}
public static int test(){
try{
int i = 1/0;
return 1;
}catch (Exception e){
return 0;
}finally {
return -1;
}
}
输出结果时0而不是1
Map.Entry entry:map.entrySet()
)List list = new ArrayList();
list.add("a");
list.add("a");
list.add("b");
HashSet set = new HashSet(list);
//清空list
list.clear();
list.addAll(set);
List list = new ArrayList();
list.add("a");
list.add("a");
list.add("b");
List newList = new ArrayList();
list.forEach(s->{
//当新list集合中没有该元素时,将该元素存入
if (!newList.contains(s)){
newList.add(s);
}
});
public static void main(String[] args) throws IOException {
FileInputStream inputStream = new FileInputStream("D:/1.png");
OutputStream outputStream = new FileOutputStream("D:/2.png");
byte []bytes = new byte[50];
while(inputStream.read(bytes)!=-1){
outputStream.write(bytes);
}
}
BIO
同步阻塞I/O,一个服务器连接对应一个线程,及客户端有连接请求时就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可用通过线程池机制来改善,BIO方式使用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中。
NIO
同步非阻塞I/O,服务器实现模式为一个请求一个线程,即客户端发送的连接请求会注册到多路复用器上,多路复用器轮询到连接有IO请求时才会启动一个线程进行处理,NIO方式适用于连接数目较多且连接比较多的架构(redis单线程却高性能也是因为底层使用到多路复用),比如聊天服务器,并发局限于应用中,编程复杂。典型的使用NIO的网络编程框架Netty
多路复用:
AIO
异步非阻塞I/O,服务器实现模式为一个有效请求一个线程,客户端的IO请求都是由操作系统先完成了再通知服务器用其启动线程进行处理,AIO方式适用于连接数目较多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程复杂
clone()方法是Object的方法,使用protect修饰,如果子类需要使用到该方法需要重写该方法,修改访问控制符为public,且实现Cloneable接口(类似序列化);克隆的对象与原对像是两个个体,互不相干
class Klass{
private String className;
public Klass(String className){
this.className = className;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
@Override
public String toString() {
return "Klass{" +
"className='" + className + '\'' +
'}';
}
}
class Student implements Cloneable{
private String name;
private Klass klass;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Klass getKlass(){
return klass;
}
public void setKlass(Klass klass){
this.klass = klass;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", klass=" + klass +
'}';
}
}
class Scratch{
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student();
student1.setName("tom");
student1.setKlass(new Klass("一班"));
Student student2 = (Student) student1.clone();
System.out.println(student1);
System.out.println(student2);
student2.setName("jack");
student2.getKlass().setClassName("二班");
System.out.println(student1);
System.out.println(student2);
}
}
结果:
Student{name='tom', klass=Klass{className='一班'}}
Student{name='tom', klass=Klass{className='一班'}}
Student{name='tom', klass=Klass{className='二班'}}
Student{name='jack', klass=Klass{className='二班'}}
这里属于浅克隆,Student实现了Cloneable接口,所以Student的字段能够被克隆出一份新的、与原来对象不相干的数据,而Klass的字段还是共用的同一个数据,所以需要将Klass的字段也实现Cloneable接口,重写Object克隆方法,并在克隆时单独对Klass进行克隆,如下修改Student的clone方法
class Klass implements Cloneable{
private String className;
public Klass(String className){
this.className = className;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Klass{" +
"className='" + className + '\'' +
'}';
}
}
class Student implements Cloneable{
private String name;
private Klass klass;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Klass getKlass(){
return klass;
}
public void setKlass(Klass klass){
this.klass = klass;
}
@Override
public Object clone() throws CloneNotSupportedException {
Student student = (Student) super.clone();
student.setKlass((Klass) student.getKlass().clone());
return student;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", klass=" + klass +
'}';
}
}
class Scratch{
public static void main(String[] args) throws CloneNotSupportedException {
Student student1 = new Student();
student1.setName("tom");
student1.setKlass(new Klass("一班"));
Student student2 = (Student) student1.clone();
System.out.println(student1);
System.out.println(student2);
student2.setName("jack");
student2.getKlass().setClassName("二班");
System.out.println(student1);
System.out.println(student2);
}
}