java基础总结

基本数据类型:

数据类型以及内存占用,单位为字节,1字节=8bit

byte:1字节,8位

char:2字节,16位

short:2字节,16位

int:4字节,32位

float:4字节,32位

double:8字节,32位

boolean:4字节,32位

这里boolean要说明一下:

根据oracle JVM规范 java 7 2.3.4小节所述

JVM规范指出boolean当做int处理,也就是4字节,boolean数组当做byte数组处理,这样我们可以得出boolean类型占了单独使用是4个字节,在数组中是确定的1个字节。

以下是官方文档地址:https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.3.4

变量类型:

静态变量:经过static修饰的,不管使用没使用,在类加载的时候会被初始化,共享内存地址.

非静态变量:在需要时才会初始化,不共享内存地址.

访问控制修饰符:

  • public:所有人,所有包皆可访问
  • protect:继承了相关类的父类和子类都可以访问,不同包也可以
  • default:同包里可以访问
  • private:同类才可以访问

非访问修饰符:

static: 静态的使其成为静态方法或者变量

final:使其成为final对象,final修饰的对象不能被改变,修饰的方法不能被重写,修饰的类不能被继承.

abstract:抽象,抽象类必须被实现,抽象类可以含有成员变量和权限修饰符,拥有抽象方法一定是抽象类,抽象类不一定会拥有抽象方法.

Synchornized:同步,在类上面加上关键字就会变成同步类,同时只能有一个线程能够对其进行访问.

循环:

for,for each,do while,while

分支:
if else{}

switch(){
		case1:

		break;
		
		case2:

	}

字符串String,StringBuffer和StringBuilder.

String是常量 字符串内容不能被改变.

StringBuffer和StringBuilder中的内容可以被改变,buffer中有同步关键字,线程安全,而builder没有, 由此可知, builder的效率要比buffer快上一些.

数组:

先声明才可以进行使用,写法:

变量类型+[]的方式:例如int[] a 可以在初始化的同时进行赋值,也可以对其元素空间大小进行开辟,通过索引进行访问,初始下标为0.

日期:Date() 日期起始时间为1970.1.1

异常处理:

Throwable:

异常分为两种 一种是error,通常会造成程序崩溃,一种是Exception.

Exception:分为IOException 和RuntimeException

异常通过TryCatch进行捕获

将需要检测的代码放入Try语句块中,catch语句块紧随其后,Catch语句块中定义捕获的异常以及对异常的处理方法.

Catch过后最好加上Finally语句块,无论出现什么异常都会被执行,在此对程序进行异常和数据处理的收尾工作,增加程序的鲁棒性.

throw和throws:

throw 抛出:对于编译器检测不到,或者没有需求的异常,可以手动进行抛出.

thorws:通过定义在方法后边,将不知道如何处理的异常向上抛出,让父类去处理,会被抛出到调用者那里,这种方法称为回避处理.

继承:类和接口可以被继承,类继承通过extends关键字,接口通过implement,接口支持多继承,类支持单继承.

多态:触发多态的条件,继承,子类重写父类方法,父类有指向子类引用.

重写:继承后,对父类同名方法进行重写.

封装:通过设定访问权限,给予访问控制.

接口:接口中的方法只能是public,接口中可以有变量但是必须是static和final的.

泛型:

泛型:

泛型即参数化类型,类似于变量, 将类型也参数化, 需要的时候传入相应属性的参数.

操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。

泛型只在编译的时候有效,在编译之后程序会采取去泛型化的措施。也就是说Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。

泛型类型在逻辑上看以看成是多个不同的类型,实际上都是相同的基本类型。

泛型的使用:类,接口,方法.

  • 泛型类:
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{ 
//key这个成员变量的类型为T,T的类型由外部指定  
private T key;

public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
this.key = key;
}

public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
return key;
}
}

泛型的类型参数只能是类类型(包括自定义类),不能是简单类型.

实例化:
//传入的实参类型需与泛型的类型参数类型相同,即为Integer.
Generic<Integer> genericInteger = new Generic<Integer>(123456);

//传入的实参类型需与泛型的类型参数类型相同,即为String.
Generic<String> genericString = new Generic<String>("key_vlaue");

定义的泛型类,就一定要传入泛型类型实参么?并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。

泛型类型的实参->new Generic<Integer>(123456); ,加粗部分就是泛型类型的实参.传入的是Generic<Integer>类型的实参123456
这个时候才会起到泛型的限制作用,

如果不传入泛型类型的实参
Generic generic2 = new Generic(55.55);那么使用的方法或者成员变量会变成任意类型. 结果为55.55
  • 泛型的类型参数只能是类类型,不能是简单类型。
  • 不能对确切的泛型类型使用instanceof操作。

泛型接口:与泛型类使用基本相同,

/**
 * 传入泛型实参时:
 * 定义一个生产器实现这个接口,虽然我们只创建了一个泛型接口Generator<T>
 * 但是我们可以为T传入无数个实参,形成无数种类型的Generator接口。
 * 在实现类实现泛型接口时,如已将泛型类型传入实参类型,则所有使用泛型的地方都要替换成传入的实参类型
 * 即:Generator<T>,public T next();中的的T都要替换成传入的String类型。
 */
public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

泛型通配符:?

可以解决当具体类型不确定的时候,这个通配符就是 ? ;当操作类型时,不需要使用类型的具体功能时,只使用Object类中的功能。那么可以用 ? 通配符来表未知类型。

使用起来:
泛型类 class classname 在类实例化时候 声明了GenerateName的类型,下面可以使用GenerateName作为泛型名称.

泛型方法:public className( varName) 返回值GenerateName声明了GenerateName 作为泛型, 所以参数可以使用.

example:
public class GenerateName<T>{
//此时子方法可以使用T作为泛型类型

public void test1(t<T> var1){
//在这个时候 方法可以成功运行, 当你指定了T的类型 那么 在编译过程中 t<T>也就被指定了,虽然使用了泛型作为实参,但是这个并不是一个泛型方法

}


public void test2(t<X> var2){
//此时不能成功运行, 编译器会提示 Unknown:class, 编译器没有找到类型为X的泛型, 此时X没有被指定, 这个也不是一个泛型方法.

}	

public <E> test3(t<E> var3){
//此时可以成功运行, 由于在方法中已经声明了<E>,编译器找到了E类型的泛型, 这是一个正确的泛型方法.

}

public<T> test4(t<T> var4)
//此泛型方法中的T与泛型类中的T不为一个类型, 是一种全新的类型.	


}	

静态方法与泛型:

态方法无法访问类上定义的泛型;如果静态方法操作的引用数据类型不确定的时候,必须要将泛型定义在方法上。

即:如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法 。

个人猜测是和类的加载顺序有关, 因为静态方法在类加载的时候会优先进行执行, 如果此时类还未被创建,就进行静态方法的加载, 肯定找不到,会报错.

泛型的上下边界:
为泛型添加上边界,即传入的类型实参必须是指定类型的子类型

public void showKeyValue1(Generic<? extends Number> obj)以这个方法为例, 传入的实参类型必须是Number的子类型,

序列化:

序列化是用于保存在JVM虚拟机停止运行后还需要存在的对象,并且当虚拟机再启动时,可以再进行读取.

在保存对象时,会把其状态保存为一组字节,在未来,再将这些字节组装成对象。必须注意地是,对象序列化保存的是对象的"状态",即它的成员变量。由此可知,对象序列化不会关注类中的静态变量。

Java枚举类型的话,应该知道每个枚举类型都会默认继承类java.lang.Enum,而该类实现了Serializable接口,所以枚举类型对象都是默认可以被序列化的。

反射机制:

反射是在运行状态中,对于类,可以知道其属性和方法, 对于对象,可以调用任意一个方法和属性.

反射的功能:

  • 运行时判断对象所属类

  • 运行时构造任意一个类的对象

  • 运行时判断任意一个类所具有的成员变量和方法.

  • 运行时调用任意一个对象的方法.

  • 生成动态代理

posted @ 2018-05-07 20:52  CurryRice  阅读(153)  评论(0编辑  收藏  举报