java总结
、
一,jdk,jre,和jvm的区别。
jdk:jdk是整个java的核心,包括了java运行环境,一堆java工具和java基础的类库。
jre:所有的java程序都要在jre下才能运行。包括jvm和java核心类库和支持文件。与jdk相比,它不包含开发工具--编译器,调试器和其它工具。
jvm:jvm是jre的一部分,它是一个虚拟出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。(一个软件调用硬件)它有针对各种操作系统的接口,它先把你的代码在虚拟机中运行,然后通过不同的接口调用适合这类操作系统的方法。汇编是把机器码传给cpu做,而java是把class文件传给jvm做。jvm有自己定义的寄存器和自己定义的操作码,然后调用操作系统的接口调用cpu。
二,this关键字
this只能用于方法方法体内。当一个对象创建后,java虚拟机就会给这个对象分配一个引用自身的指针,这个指针的名字就是this。
1,通过this调用另一个构造方法,用法是this(参数列表 )
1.1调用其他的构造方法必须在第一行
1.2至少有一个构造方法是不用this调用的
2,函数参数或者函数中的局部变量和成员变量同名的情况下
3,表示当前对象
五,继承的规则。
1,构造方法不能被继承,方法和属性可以被继承。
2,子类的构造方法隐含的调用父类的默认构造方法
3,如果父类中没有默认的构造方法,子类构造方法的第一行必须通过super(。。)调用父类的构造方法。
4,子类实例化过程 1,先调用父类构造2,调用子类构造。
5,class A{
public A(){} // 1:无参数构造方法。
public A(String s){} // 2.
}
class B extends A{
public B(String s){
super(s); // 3.
}
}
说明:如果没有1处的无参数构造方法,那么3处一定要主动调用父类带参数的构造方法。
如果有1处的构造方法,那么3处代码可以不要,因为Java会自动默认调用父类的无参数构造方法。
记住一点:在构造子类时,一定会调用到父类的构造方法。
所以父类要么有一个默认的无参数构造,这样Java会自动调用这个无参数的构造。如果父类没有无参数的构造,那么就要你自己在子类的构造中,通过super()的方式调用父类的构造
六:




继承关系中的初始化顺序是,先初始化父类,完了在初始化子类。单个类的初始化顺序是先赋默认值,在显示初始化,在构造代码块,最后构造初始化。
七,类的生命周期
首先来了解一下jvm(java虚拟机)中的几个比较重要的内存区域,这几个区域在java类的生命周期中扮演着比较重要的角色:
1,方法区:在java的虚拟机中有一块专门用来存放已经加载的类信息、常量、静态变量以及方法代码的内存区域,叫做方法区。
2,常量池:常量池是方法区的一部分,主要用来存放常量和类中的符号引用等信息
3,堆区:用于存放类的对象实例。
4,栈区:也叫java虚拟机栈,是由一个一个的栈帧组成的后进先出的栈式结构,栈桢中存放方法运行时产生的局部变量、方法出口等信息。当调用一个方法时,虚拟机栈中就会创建一个栈帧存放这些数据,当方法调用完成时,栈帧消失,如果方法中调用了其他方法,则继续在栈顶创建新的栈桢。
其次,当我们编写一个java的源文件后,经过编译会生成一个后缀名为class的文件,这种文件叫做字节码文件,只有这种字节码文件才能够在java虚拟机中运行,java类的生命周期就是指一个class文件从加载到卸载的全过程。 一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况,如图所示:
加载:
在java中,我们经常会接触到一个词——类加载,它和这里的加载并不是一回事,通常我们说类加载指的是类的生命周期中加载、连接、初始化三个阶段。在加载阶段,java虚拟机会做什么工作呢?其实很简单,就是找到需要加载的类并把类的信息加载到jvm的方法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。
类的加载方式比较灵活,我们最常用的加载方式有两种,一种是根据类的全路径名找到相应的class文件,然后从class文件中读取文件内容;另一种是从jar文件中读取。另外,还有下面几种方式也比较常用
从网络中获取:比如10年前十分流行的Applet
根据一定的规则实时生成,比如设计模式中的动态代理模式,就是根据相应的类自动生成它的代理类
连接:
连接阶段比较复杂,一般会跟加载阶段和初始化阶段交叉进行,这个阶段的主要任务就是做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步骤:验证、准备和解析。
1,验证:当一个类被加载之后,必须要验证一下这个类是否合法,比如这个类是不是符合字节码的格式、变量与方法是不是有重复、数据类型是不是有效、继承与实现是否合乎标准等等。总之,这个阶段的目的就是保证加载的类是能够被jvm所运行。
2,准备:准备阶段的工作就是为类的静态变量分配内存并设为jvm默认的初值,对于非静态的变量,则不会为它们分配内存。有一点需要注意,这时候,静态变量的初值为jvm默认的初值,而不是我们在程序中设定的初值。jvm默认的初值是这样的:
-基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。
-引用类型的默认值为null
-常量的默认值为我们程序中设定的值,比如我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100
3,解析:在内存中也是一样,比如我们要在内存中找一个类里面的一个叫做show的方法,显然是找不到。但是在解析阶段,jvm就会把show这个名字转换为指向方法区的的一块内存地址,比如c17164,通过c17164就可以找到show这个方法具体分配在内存的哪一个区域了。这里show就是符号引用,而c17164就是直接引用。在解析阶段,jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。
初始化:
如果一个类被直接引用,就会触发类的初始化。在java中,直接引用的情况有:
通过new关键字实例化对象、读取或设置类的静态变量、调用类的静态方法。
过反射方式执行以上三种行为
初始化子类的时候,会触发父类的初始化
作为程序入口直接运行时(也就是直接调用main方法)
类的初始化过程是这样的:按照顺序自上而下运行类中的变量赋值语句和静态语句,如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。在类的初始化阶段,只会初始化与类相关的静态赋值语句和静态语句,也就是有static关键字修饰的信息,而没有static修饰的赋值语句和执行语句在实例化对象的时候才会运行。
使用:
类的使用包括主动引用和被动引用,主动引用在初始化的章节中已经说过了,下面我们主要来说一下被动引用:
引用父类的静态字段,只会引起父类的初始化,而不会引起子类的初始化
定义类数组,不会引起类的初始化
引用类的常量,不会引起类的初始化
卸载:
关于类的卸载,笔者在单例模式讨论篇:单例模式与垃圾回收一文中有过描述,在类使用完之后,如果满足下面的情况,类就会被卸载
该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例
加载该类的ClassLoader已经被回收
类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法
如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程其实就是在方法区中清空类信息,java类的整个生命周期就结束了
总结:
做java的朋友对于对象的生命周期可能都比较熟悉,对象基本上都是在jvm的堆区中创建,在创建对象之前,会触发类加载(加载、连接、初始化),当类初始化完成后,根据类信息在堆区中实例化类对象,初始化非静态变量、非静态代码以及默认构造方法,当对象使用完之后会在合适的时候被jvm垃圾收集器回收。读完本文后我们知道,对象的生命周期只是类的生命周期中使用阶段的主动引用的一种情况(即实例化类对象)。而类的整个生命周期则要比对象的生命周期长的多。
一段代码,当虚拟机发现一个类名出现时,就会加载它,找到它的字节码文件,把信息注册到方法区。接着连接它,验证它能否被jvm运行,为静态变量(此时变量的值都是默认值不是0就是null)和静态常量赋初值(准备),把方法名映射到内存地址上(解析)。当出现new关键字实例化对象,读取或者设置类的静态变量或者调用类的静态方法,就会初始化类。即自上而下的运行类中的变量赋值语句和静态代码块。
八,java ee 中的url问题
这里的action为什么是../helloworld呢? 因为该jsp页面是位于test文件下,也就是http://localhost:8080/ServletTest/test/index.jsp 而../后 目录变成了
http://localhost:8080/ServletTest/ 此时再加上helloworld 正好组成了xml中配置的
http://localhost:8080/ServletTest/helloworld 对应的servlet路径
<form action="/helloworld" method="get">
<input type="submit" value="提交">
</form>
web.xml的 / 表示的是http://localhost:8080/ + 工程名
而jsp的action
加了 /的时候表示绝对路径http://localhost:8080/ ;
而没有加 / 表示的是相对路径
七;
Class<T> t 的含义: 声明一个只对T友好的Class类 t:、
八:
类加载器可能根据类的位置找到文件,通过流的方式加载类到内存中去。
反射的Class 可能就是对应的.Class文件。
九:在Java中, 创建一个对象常常需要经历如下几个过程:类的初始化(加载,连接(验证,准备,解析),初始化,使用,卸载):1,准备阶段:类变量赋内存并赋初值。2,初始化:类变量初始化,静态代码块执行。
对象的实例化:成员变量赋内存,初始化,实例代码块,构造函数。
十:集合:List ArrayList:有序,可重复,线程不安全,底层是数组,查询快,增删慢。
LinkedList: 有序,可重复,线程不安全,底层是连表,查询慢,增删快。Vector 线程安全,效率低。
Set
HashSet():无序,不可重复。线程不安全
linkedHashSet :有序,可重复,线程不安全。
treeset():无序,不可重复,线程不安全。红黑树算法。
Map
HashMap:无序,不可重复,线程不安全。
LinkedHashMap:有序,不可重复,线程不安全
TreeMap:有序,不可重复,
十一:final:修饰类类不能继承,修饰方法不能被重写,修饰变量表明为常量,不可改变。
finally:try catch finally块 最终都会执行。
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。
十二:object的方法:registerNatives,getClass,hashCode,equals,clone,toString,notify,notifyall,wait,finalize
十三:jdk和cglib的区别:jdk,先生成代理类模板字节码,再通过反射实例化一个代理类对象。cglib:同样是先生成代理类模板字节码,再通过反射实例化一个代理类对象。生成的类继承自被代理类。 区别:jkd动态代理,对象的方法执行是通过反射方式执行。而cglib的代理对象方法执行是通过对方法的直接调用。
cglib是执行Intercepter方法。执行完加强的语句后,执行invokesuper,这里FastClass类对对象进行特殊的处理,比如会将方法的引用存起来,直接进行调用。
十四:线程的状态:初始(线程被构建,但未调用start方法),
就绪:线程对象启用start方法。处于就绪状态的线程随时会被cpu调度执行。
运行(调用start方法后,在java线程,将操作系统就绪和运行统称运行状态,如果直接得到锁一直运行,如果需要竞争锁,则进入阻塞状态,竞争到锁再进入就绪状态),
阻塞(线程等待进入synchronized代码块或方法中,等待获取锁。注:进入阻塞状态的唯一前提是在等待同步锁,Lock类对于锁的实现不会令线程进入阻塞状态,lock底层调用locksupport.park()方法,使线程进入的是等待状态),
等待(线程可调用wait,jion等操作使自己陷入等待状态,并等待其他线程做出唤醒,唤醒之后再去竞争锁,竞争到锁后进入就绪状态),
超时等待(线程调用sleep(timeout),wait(timeout),进入超时等待状态,超时后自行返回),
死亡。
锁的种类:公平锁(公平锁是指多个线程按照申请锁的顺序来获取锁),非公平锁。
可重入锁:一个同步方法可以调用另外一个同步方法,一个线程已经拥有某个对象的锁,再次申请的时候仍然会得到该对象的锁。
①wait和sieep的区别:sleep是Thread类中的方法,wait是object类中的方法。sleep导致程序暂停执行指定的时间,让出cpu,但不释放锁,到达指定的时间继续执行。一旦一个对象调用wait方法,必须要采用notify()或notifyall()方法唤醒该线程。如果线程拥有某个对象或某些对象的同步锁,那么在调用wait之后,这个线程会释放他所持有的同步资源,而不限于这个被wait的对象。
②wait notify:wait方法可以使线程进入等待状态,notify可以使唤醒等待状态。使用场景:生产者消费者。
③join和yeild的区别:

悲观锁,乐观锁:悲观:拿数据会上锁,乐观:拿数据不会上锁,写数据会上锁 cas是乐观锁的一种实现方式。
十五:jvm:jvm是运行在操作系统上层来和计算机硬件来沟通,jvm有三个系统,分别是类加载子系统,执行引擎,运行时方法区。其中类加载器有三种:1,启动类加载器:加载 JRE/lib/rt.jar目录中。2,拓展类加载器JRE/lib/etc3,系统类加载器:加载当前应用下的jar和class. 类加载机制的原理:①双亲委派机制:当类在需要加载的时候才被加载,系统加载器类会委派给拓展类加载器看看在你的加载路径里吗,而拓展器加载器类会委派给系统类加载器类看看在你的加载路径里吗?②,可见性机制:子类加载器可以看到父类加载器加载的类。③单一性机制,父类加载器加载的类子类无法继续加载。运行时内存区:堆,全局方法区,线程共享。栈(局部变量表,操作数栈,动态链接地址,返回地址),本地方法栈,程序计数器,线程私有。
堆:新生代(EDEN,Survivur(FromSpace和ToSpace),),老年代,永久代。年轻代:老年代=3:1.而年轻代里EDEN:Suivivor=8:1。先被分配到Eden区,然后第一次MinorGc后会被移到suivivor区,如果在survivor区熬过一次minorGC年龄会加一。当年龄到一定岁会移到老年代。新生代的垃圾算法是复制算法不会产生碎片。垃圾回收算法:引用计数算法,可达性分析算法(局部变量表里的对象,方法区中常量引用的对象,类变量引用的对象,本地方法栈引用的对象)。标记清除算法,复制算法,分代清楚算法。
垃圾收集器:cms收集器(标记清楚算法) g1(标记整理算法)
什么时候触发:新对象生成在eden空间申请不了时会触发minorgc,把eden和from的对象移到to。其中from的年龄到达一定岁数会移到old。
如果年老代满了,会触发fullgc。持久态满了,system.gc,。
十六:类集源码与锁:HashMap 数据结构是一个数组,和单链表。结构是Node<K,V>{K key;V value; Node<K,V> node}扩容。1.8后,如果单链表长度就将其结构改成红黑树了。synchronized和luck的区别:①synchronized是关键字,jvm层次的,luch是类。②获取锁的线程执行完代码后释放锁,luckfinnaly最终要释放锁。③synchronized是不公平锁,luck可公平也不可公平。 抽象的队列式同步器。ReentrantLock的lock()默认是获取非公平锁。
十七:mysql的引擎:Innodb,和MYISAM 。innodb有行锁,事务。事务的隔离级别:读未提交(脏读,不可重复读,幻读),读已提交(不可重复读,幻读),可重复读(mvcc历史版本控制,如果没有则先去数据库里查,幻读),可串行化。
十八:事实上i++和++i在底层的实现都是先自增,区别在于返回值.i++返回自增前的值,++i返回自增后的值 ①y=0;x=y++;x=0 y=1 (y入栈,复制栈顶数值并将复制值压入栈顶,1入栈,栈顶两元素出栈相加结果入栈,出栈给y,出栈给x) ②y=0;x=++y ;x=1 y=1 (y入栈,1入栈,栈顶两元素出栈相加,把结果入栈,复制栈顶元素并将复制值入栈,出栈给y,出栈给x)③x=0;x=x++ ; x = 0(x入栈,dup(复制栈顶元素并入栈),1入栈,栈顶两元素出栈,相加,结果入栈,出栈给x,出栈给x) ④x= 0 ;x=++x; x=1(x入栈,1入栈,栈顶两元素出栈相加结果入栈,复制栈顶两元素并将复制值入栈,出栈给x,出栈给x)。
十九:红黑树的性质:性质一:节点是红色或者黑色。性质二:根节点是黑色。性质三:每个叶节点(NIL节点,空节点)是黑色。性质四:每个红色节点的两个子节点都是黑色。即,从每个叶子到根的所有路径上不能有两个连续的红节点。性质五:从任一节点到其每个叶子节点的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键性质:从根到叶子的最长可能路径不多于最短的可能路径的两倍
二十:接口和抽象类的区别:接口默认的方法都是public abstract,而抽象类可以是protected abstract。抽象类可以实现方法,而接口不能。抽象类的变量可以有任何形式的修饰。但是interface类型的只能是public static final类型的。接口中不能有静态方法和静态代码块。
二十一:Throwable接口,Error和Exception都继承自Throwable接口。异常又分运行时异常,和编译时异常。不受检异常为Error和runtimeExcepiton .其他的Excepion之外的都是受检异常。
spring事务管理默认是针对不受检的异常回滚。也就是默认对Error和RuntimeExcption。

二十二:排序算法,①冒泡算法,第一个和第二比较,如果第二个大于第一个颠倒顺序,第二个和第三个比较,直到倒数第二个最后一个比较。这个时候最后一个是最大的。然后再重复但是不用再比较最后一个了。②
二十三:hashcode方法的作用:为了配合散列的集合进行正常的运作。这些散列的集合包括hashset,hashmap,hashtable。因为集合不允许重复,因此怎么判断要插入的对象是否已经重复了呢?可以拿这个对象的hashset
二十四:java01存储:位与&(二元操作符,相同位上两个都是1才为1,00 和01做位与 00)。位或|(两元运算符,00和01作位或,相同位上有一个有1,则为1 01) 。位异或^(两元操作符,相同位上只有一个是1,才为1 00和01做异或操作,01)。位非~(一元操作符,输出当前位相反的值)
二十五:volatile:当cpu操作变量的时候,如果发现变量是共享变量的时候,操作的时候会把缓存数据写到主存里。其他cpu再访问这个变量的时候会直接去主存里取。并发编程的三个特性:原子性,可见性,有序性。要想并发程序安全执行三个特性必须都保证。知识点:happen-befor:在前的操作happen-befor在后的操作。重排序(a = new A(),发生重排序,1,分配内存空间2,初始化对象3,将内存空间的地址赋给对应的引用。2和3会发成重排序),单线程不影响结果。
二十六:synchronized修饰普通方法,修饰静态方法,修饰代码块。普通方法锁的是对象,静态方法锁的是访问字节码,两个锁不是一个锁。修饰代码块可以对类进行加锁,也可以对对象进行加锁。
volatile和synchronized的区别:volatile不保证原子性。synchronized保证原子性。 volatile更改的是公共内存区的数据,synchronized更改的是自己工作内存区的数据。
二十七:hashmap原理:hashmap的数据结构是数字加链表的存储方式,当发生哈希碰撞的时候会把节点追加到链表上,1.8当节点的长度大于8的时候会转成红黑树。hashmap节点数组的默认长度是16,加载因子是0.75。当数组的大小大于临界值时会进行扩容。hashmap有两个线程不安全的地方,一个是put的时候会覆盖,另一个是扩容的时候节点死循环。
二十八:concurrentHahsMap如何保证线程安全:1,使用Unsafe类和cas。unsafe类保证原子操作,如果直接插的话就用cas,如果需要遍历的话,就对头结点加锁。
二十九:rabbitmq知识点:rabbitmq是一个应用就像mysql,生产者往mq的队列里投递消息,消费者读取或订阅队列里的消息。rabbitmq的核心组件是Exchange和Queue。Exchage类似数据通讯网络中的交换机,提供路由策略。生产者在传递消息的时候,会传递一个routing_key,Exchange会根据这个routing_key按照特定的路由路由算法,将路由消息给指定的queue。Exchage有四种类型:direct(直接交换机),fanout(广播),topic(主题式交换器),header(消息体的header匹配)。假设p1和c1都注册了相同的Broker,Exchage,和queue。p1发送的消息最终会被c1消费。基本的通信流程:1,p1生产消息,发送给服务端的exchage。2,exchange收到消息,根据routing_key,将消息转发给匹配的queue,3,queue收到消息将消息发送给订阅者c1。4,c1收到消息发送ack给队列确认收到消息。5,queue收到ack删除,删除队列中缓存的此消息。
mq面试:(如何保证消息的可靠性传输?)1,,生产者往mq丢数据,由于网络问题,mq没有收到怎么办?①选择mq提供的事务功能,就是生产者发送数据之前开启mq事务,饭后发送消息,如果消息没有成功被mq接受到,生产者会收到异常报错,此时就会回滚事务,然后重试发送消息;②开启confirm模式,生产者那里设置开启confirm模式之后,你每次写的消息都会分配一个唯一的id,然后如果写入了mq中,mq会给你回传一个ack,告诉你消息ok了。
2,消费者传送ack网络问题,mq没有收到,重复消费。保证消息消费的幂等性。保证多条相同的数据过来的时候只处理一条或者多条处理结果和处理一条的结果相同。例如给消息加唯一约束,每次消费成功的把唯一约束存到redis,设置失效时间。这样在业务开始时查看redis里有没有这个唯一约束。
三十:freemark:1,freemark模板不编译为类,而class文件会存放在jvm的永久代里,所以使用freemark避免永久代oom。2,freemark根据模板直接生成好html,这样访问的时候直接访问的就是html,效率比较高。 freemark判空??
三十一:分布式quartz:schedule调度器。job任务。trigger触发器。
负责任务调度的几个线程:①任务执行线程:通常使用一个线程池维护一组线程,负责每个job的实际执行。②schedule调度线程:轮询所有的trigger如果有需要触发的trigger,则从任务执行线程池中获取一个空闲线程,执行与该trigger关联的任务。
三十二:项目架构:
三十三:cloud的组件及其作用:
1,注册中心erueak:在注册中心中找到服务和服务地址的关系映射。服务注册后,如何被及时发现。服务宕机后如何及时下线。服务如何有效的水平拓展。服务发现时如何路由。服务异常后如何进行降级。如何做高可用。
2,客户端负载均衡:Ribbon
3,断路器:Hystrix
4,网关:zuul
5,分布式配管中心:cloud config。
三十四:单点登录:不同的系统去请求统一的sso服务器,把用户信息存到session里,客户端存cookie。由于cookie的域名不同不能跨域请求,我们使用cors跨域资源共享解决跨域问题。
三十五:aop的使用场景:事务,权限,日志,缓存,内容传递,链路追踪
spring默认的aop策略是:如果目标类是接口就使用jdk的,否则使用cglib的。
浙公网安备 33010602011771号