Xmx: 最大堆大小,Xms: 初始堆大小,Xmn:年轻代大小
XXSurvivorRatio: 年轻代中Eden区于Survivor区的大小比值 年轻代5120m
Eden: Survivor = 3, Survivor区大小 =1024m (Survivor区有两个,即将年轻代分为5份,每个Survivor区占一份),总大小为2048m。
-Xms初始堆大小即内存值为1024m
关于构造方法:
1.构造方法的方法名必须与类名保持一致
2.构造方法没有返回类型,也不能定义为void,在方法名前面不声明方法类型
3.构造方法的主要作用是完成对象的初始化工作,他能够把定义对象时的参数传递给对象的域
4.一个类可以定义多个构造方法,如果在定义类的时候没有定义构造发,则编译系统会自动插入一个无参数的默认构造器,这个构造器不执行任何代码
5.构造方法可以重载,以参数的个数,类型,顺序。
A: LinkedList实现了List接口,而不是继承 B: AbstractSet类实现了Set接口
C: HashSet继承AbstractSet类,同时也实现了set D: WeakMap是js里的东西
基本类型都有默认值,boolean的默认值为false 但是包装类的默认值都是null
ASCII码不都是可打印字符,ASCII中还包含了一些特殊的空字符
DataOutputStream,这个是直接把字节码写入文件的输出流,和编码没有关系,因为根本没有转成字符 直接4+2
类的访问控制符只有三种: public、private、protect
static和访问控制无关
在 java中 声明一个数组时,不能直接限定数组的长度。只有在创建实例化对象的时候,才能给定数组长度
public class Test4 { private static int i=1; public int getNext(){ return i++; } public static void main(String[] args) { Test4 test = new Test4(); Test4 testObject = new Test4(); test.getNext(); testObject.getNext(); System.out.println(testObject.getNext()); } }
return i++,先返回 i,然后i+1;
第一次调用getNext()方法时候,返回的是1,但此时i=2;
第二次调用getNext()方法时候,返回的是2,但此时i=3;
第三次调用getNext()方法时候,返回的是3,但此时i=4;
public class Test5 { public static void main(String[] args) { int num = 10; System.out.println(test(num)); } public static int test(int b){ try { int a = 1/0; b+= 10; return b; }catch (RuntimeException e) { }catch (Exception e2) { }finally { b+=10; return b; } } }
当 finally中return 则覆盖之前的 return语句
intValue()是把Integer对象类型变成Int的基础数据类型
pareseInt( )是把String解析成 int的基础数据类型
ValueOf()是把String转成Integer对象类型
synchronized: 具有原子性,有序性和可见性;(三个都有)
volatile:具有有序性和可见性(缺一个原子性)
ABD:都可用于float和double、只有%取余操作,只适用于整型
--------------------------------------------------------------------------------------------
堆区:只存放类对象,线程共享
方法区:又叫静态存储区,存放class文件和静态数据,线程共享、
栈区:存放方法 局部变量,基本类型变量区、执行环境上下文、操作指令区,线程不共享。
1.继承Thread类,重写run方法;
2.实现Runnable接口,实现run方法
3.实现Callable接口,重写call方法
4.使用线程池产生线程对象。
线程安全概念:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。
public class Test6 { public void add(Byte b){ b = b++; } public void test(){ Byte a = 127; Byte b = 127; add(++a); System.out.println(a+" "); add(b); System.out.println(b+" "); } }
LinkedList 和 ArrayList 都是不同步的,线程不安全; Vector 和 Stack 都是同步的,线程安全; Set是线程不安全的; Hashtable的方法是同步的,线程安全; HashMap的方法不是同步的,线程不安全;
类的加载是由类加载器完成的。类加载器包括根加载器(Bootstrap)、扩展加载器(Extension)、
系统加载器(System)和用户自定义类的加载器(java.lang.ClassLoader的子类)。从jdk1.2开始,类加载过程采用了父亲委托机制(PDM).PDM更好地保证了java平台的安全性。在该机制中,JVM自带的Bootstrap是根加载器,其他的加载器都有且有一个父类加载器吗,类的加载首先请求父类加载器加载,父类加载器无能为力的时候才由其子类加载器自行加载,JVM不会向Java程序提供BootStrap的引用。
BootStrap: 一般用本地代码实现,负责加载JVM基础核心类库(rt.jar)
Extension: 从Java.ext.dirs系统属性所指定的目录加载类库,它的父加载器是BootStrap
System class loader: 又称为应用类加载器,其父类是Extension,它是应用最广泛的类加载器,他从环境变量classpath或者系统属性java.class.path所指定的目录中加载类,是用户自定义加载器的默认父加载器
用户自定义类加载器:java.lang.ClassLoader的子类
父类委托机制可以修改,有些服务器是自定义类加载器优先
后台线程:指为其他线程提供服务的线程,也称为守护线程。JVM的垃圾回收线程就是一个后台线程。
前台线程:是指接受后台线程服务的线程,其实前台后台线程是联系在一起,就像傀儡和幕后操纵者一样的关系。傀儡是前台线程、幕后操纵者是后台线程。由前台线程创建的线程默认也是前台线程。可以通过isDaemon()和setDaemon()方法来判断和设置一个线程是否为后台线程(守护线程)。
main()函数即主函数,是一个前台线程,前台进程是程序中必须执行完成的,而后台线程则是java中所有前台结束后结束,不管有没有完成,后台线程主要用与内存分配等方面。
MS收集器是一种以获取最短回收停顿时间为目标的收集器,它是基于标记清除算法实现的,它的运作过程相对于其他收集器来说要更复杂一些,整个过程分为四个步骤,包括:初始标记、并发标记、重新标记、并发清除。其中初始标记、重新标记这两个步骤需要暂停整个JVM。
- 初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快。
- 并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。
- 重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短。
- 并发清除阶段,清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。
示意图如下:
---
Java基本数据类型转换:byte、short、char—>int—>long—>float—>double
由低精度到到精度可以自动转换,而高精度到低精度会损失精度,故需要强制转换。
故第三行,小数默认为double型(float型需要在数字后面加f),不强转编译出错。
第四行,Double到double可以自动拆箱,但向下还是需要强转,再加上 l 的类型错误,故编译出错。
第二行,包装类自动装箱,没问题
ThreadLocalMap中使用开放地址法来处理散列冲突,
而HashMap中使用的是分离链表法。
之所以采用不同的方式主要是因为:在ThreadLocalMap中的散列值分散得十分均匀,很少会出现冲突。并且ThreadLocalMap经常需要清除无用的对象,使用纯数组更加方便。
1、ThreadLocal的类声明: public class ThreadLocal<T> 可以看出ThreadLocal并没有继承自Thread,也没有实现Runnable接口。所以AB都不对。 2、ThreadLocal类为每一个线程都维护了自己独有的变量拷贝。每个线程都拥有了自己独立的一个变量。 所以ThreadLocal重要作用并不在于多线程间的数据共享,而是数据的独立,C选项错。 由于每个线程在访问该变量时,读取和修改的,都是自己独有的那一份变量拷贝,不会被其他线程访问, 变量被彻底封闭在每个访问的线程中。所以E对。 3、ThreadLocal中定义了一个哈希表用于为每个线程都提供一个变量的副本: static class ThreadLocalMap { static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } } /** * The table, resized as necessary. * table.length MUST always be a power of two. */ private Entry[] table; }
---
初始list{5,3,1}
nums.add(6) // list {5,3,1,6} nums.add(0,4) // 在索引为0的下标添加元素4 =>list{4,5,3,1,6} nums.remove(1) // 删除索引为1的下标 => list{4,3,1,6}
基本上平常我们使用到的都是非线程安全的集合类,因为要使线程安全,可以通过加锁来实现。势必会造成性能上的降低,如:hashset、hashmap、arraylist、treemap、stringbulider等
像Stringbuffer、vector、hashtable这些都是专门用于多线程的。再或者以concurrent(同时发生的)为前缀的集合类大多是线程安全的。
在java中有五种方式来创建对象:
1.使用new 关键字
2.使用反射的Class类的newInstance( )方法
3.使用反射的Constructor类的newInstance( )方法
4.使用对象克隆 clone( )方法
5.使用反序列化(ObjectInputStream)的 readObject()方法
不同类型运算时以高精度的为准。根据情况需要进行强制类型转换
实现多态:1.父类的引用指向子类对象。2.子类重写父类方法
Apache就是一个Http服务器,Tomcat是一个web容器,静态的htmlApache还可以处理,但是动态的需要转发给Tomcat去处理,比如jsp页面,请求先经由Apache转发给Tomcat在由Tomcat解析请求 。
servlet接受请求,产生相应,web容器才是转换请求的
servlet的生命周期分为5个阶段:加载、创建、初始化、处理客户请求、卸载
1.加载:容器通过类加载器使用servlet类对应的文件加载servlet
2.创建:通过调用servlet构造函数创建一个servlet对象
3.初始化:调用init方法初始化
4.处理客户请求:每当有一个客户请求,容器就会去创建一个线程来处理客户请求
5.卸载:调用destroy方法让servlet自己释放其占用的资源
静态块和静态属性的优先级是相同的,按照先后的顺序执行
final是表示最终的意思,他修饰的类是不能被继承的,final修饰的方法能被继承
final可用于声明属性、方法和类,分别表示属性不可变、方法不可重写、类不可被继承。final修饰的方法是可以被重载的
Arraylist默认数组大小是10,扩容后的大小是扩容器的1.5倍,最大值小于Integer的最大值减8
如果新创建的集合带有初始值,默认就是传入的大小,也就是不会被扩容。
常量池属于 PermGen(方法区)
接口方法默认是public abstract的,且实现该接口的类中对应的方法的可见性不能小于接口方法的可见性
因此也只能是 public的
Stream结尾的都是字节流,reader和writer结尾都是字符流 两者的区别就是读写的时候一个是按照字节读写,一个是字符读写,实际使用差不多,在读写文件需要对内容按行处理,比如比较特定字符,处理某一行数据的时候一般会选择字符流,只是读写文件,和文件的内容无关,一般选择字节流
java8,switch支持10种类型
基本类型:byte、char、short、int
包装类 :Byte、Short、Character、Integer、String、enum
实际只支持int类型 Java实际只能支持int类型的switch语句,那其他的类型时如何支持的
a、基本类型byte char short 原因:这些基本数字类型可自动向上转为int, 实际还是用的int。
b、基本类型包装类Byte,Short,Character,Integer 原因:java的自动拆箱机制 可看这些对象自动转为基本类型
c、String 类型 原因:实际switch比较的string.hashCode值,它是一个int类型
d、enum类型 原因 :实际比较的是enum的ordinal值(表示枚举值的顺序),它也是一个int类型 所以也可以说 switch语句只支持int类型
length()方法是求String字符串对象中字符的个数,length方法是求数组中有多少个元素。
str.split(',') 返回的是一个数组 即使找不到分隔符,他也依然会返回一个数组,然后数组的值是1
HashMap底层是哈希表 ,而java中哈希表是由数组+链表实现的,每一个数组的节点称为bucket桶,当桶中由多个元素的时候就以链表的方法进行存储,当添加元素的时候,也是通过key的hash算法得出hash值,然后通过hash值映射出存在在哪个桶中,如果桶中没有元素,就添加成功,如果桶中有元素那就代表散列冲突,比较已存在的元素和新插入元素的hash值是否相等,如果没有相等的就则添加成功,如果某个元素的hash值和新元素的哈市值相同,则调用key的equals方法进行比较,为true则新的值覆盖掉旧的值,为false添加成功。
当桶中的元素>8并且数组长度>64 链表就会转换成红黑树。
input和output值得是对于程序而言,input是从文件读取进来,output是输出到文件
导包只可以导到当前层,不可以再导入包里的包中类
重载是在同一个类中,有多个方法名相同,参数列表不同(参数个数不同,参数类型不同),与方法的返回值无关,与权限修饰符无关。
class Chinese{ private static Chinese objref =new Chinese(); private Chinese(){} public static Chinese getInstance() { return objref; } } public class TestChinese { public static void main(String [] args) { Chinese obj1 = Chinese.getInstance(); Chinese obj2 = Chinese.getInstance(); System.out.println(obj1 == obj2); } }
单例模式:
第一步,不让外部调用创建对象,所以把构造器私有化,用private修饰
第二步, 怎么让外部获取本类的实例对象?通过本类的一个方法,供外部调用获取实例,由于没有对象调用,所以此类方法使用static修饰
第三步,通过此方法返回实例对象,由于类方法(静态方法)只能调用静态方法,所以存放该实例的变量改为类变量,用static修饰
最后,类变量,类方法是加载是在类加载时初始化的,只加载一次。所以由于外部不能创建对象,而且本来实例旨在类加载时创建一次。
use -a 是依赖关系
has -a 一般是组合关系
is -a一般是继承关系
count++先返回再自增,++count先自增再返回
// count++ 相当于 int t = count; count = count + 1; return t;
class C { C() { System.out.print("C"); } } class A { C c = new C(); A() { this("A"); System.out.print("A"); } A(String s) { System.out.print(s); } } class Test extends A { Test() { super("B"); System.out.print("B"); } public static void main(String[] args) { new Test(); } }
初始化过程是这样的:
1.首先,初始化父类中的静态成员变量和静态代码块,按照再程序中出现的顺序初始化
2.然后,初始化子类中的静态成员变量和静态代码块,按照再程序中出现的顺序初始化
3其次,初始化父类的普通成员变量和代码块,在执行父类的构造方法
4最后,初始化子类的普通成员变量和代码块,在执行子类的构造方法
1.初始化父类的普通成员变量和代码块,执行 C c = new C(); 输出c 2.super("B");表示调用父类的构造方法,不调用父类的无参构造 函数,输出B 3.System.out.print("B");
记住一点即可,引用数据类型传递了地址。只是把地址给了方法的变量,你可以通过地址修改值,但是你修改地址不会影响我原来是的指向。
D选项 由于Square没有重写Object的equals方法 ,所以调用的是Object类的equals方法 源码如下
public boolean equals(Object obj){ return (this == obj); }
这里equals比较的是值,a是一个引用,s是一个long类型的值,所以两者没有可比性
JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)
- 栈区:
- 每个线程包含一个栈区,栈中只保存方法中(不包括对象的成员变量)的基础数据类型和自定义对象的引用(不是对象),对象都存放在堆区中
- 每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
- 栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
- 堆区:
- 存储的全部是对象实例,每个对象都包含一个与之对应的class的信息(class信息存放在方法区)。
- jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身,几乎所有的对象实例和数组都在堆中分配。
- 方法区:
- 又叫静态区,跟堆一样,被所有的线程共享。它用于存储已经被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
既然是实现接口,就要实现接口的所以方法,相当于重写方法,方法的重写需要满足:三同一大一小(方法名、返回值类型、形参相同;访问权限>=重写前;抛出异常<=重写前)
牢记 方法内定义的变量没有初始值,必须要进行初始化。类中定义的变量可以不需要赋初始值,默认初始值为0;
(方法中定义的书局部变量 使用之前必须进行初始化,方法之外定义的是全局变量,默认初始化)
三元运算符 真取前面 假取后面