发表时间:2022-03-25来源:网络
一种跨平台性的面向对象语言,它的跨平台性表现在JVM实现了一次编译、到处运行。
将java代码通过编译器转换成字节码文件(.class文件)
相同的字节码在不同的操作系统内部的JVM解析出来的结果是一致的。
核心是过程两个字,过程即解决问题的步骤,从上往下步步求精,最重要的是模块化的思想。
面向对象离不开面向过程。例如造车,面向对象则是研究车这个对象是由什么组成的,需要的哪些小零件对象,强调的是对象组成,而每一个小零件的制作过程对应的就是一个个过程要经过一道道工序才能做出来,强调的是面向过程。
把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
{高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合是仅暴露少量的方法给外部使用,尽量方便外部调用。}
实现-通过访问修饰符来控制访问的权限,java有4种访问修饰符,public、private、protected、default
修饰符同一个类同一个包子类所有类public√√√√protected√√√×default√√××private√×××
1.public表示可以被该项目的所有包中的所有类访问
2.protected表示可以被同一个包的类以及其他包中的子类访问
3.default表示没有修饰符修饰,只有同一个包的类能访问
4.private 表示私有,只有自己类能访问
class A{ public String name; //所有类、包均可访问该属性,通过类名调用 private int grade; //必须创建该类,通过类自己调用,其他类不可访问,也不可调用 protected double height; //所有子类,共同的包下均可调用,其他不可访问 default String place; //默认情况下调用 }可以让某个类型的对象获得另一个类型的对象的属性的方法。
它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。
子类继承父类,可以得到父类的全部属性和方法 (除了父类的构造方法),但不见得可以直接访问(比如,父类私有的属性和方法)。
继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用父类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力;
讲到继承,不得不提一下抽象类与接口,面试中常被问到,抽象类与接口的区别,这里就提前总结一下吧 区别
参数抽象类接口默认的方法实现有默认方法的实现,抽象方法可有可无java8之后接口有了默认方法的实现,java8之前没有实现extend,可继承实体类(必须有明确的构造方法),只能单继承implement,多重继承(一个类可实现多个接口)构造器可有构造方法不可有构造方法与正常java类的区别除了不能实例化,其他差不多一样完全不同的类型访问修饰符public、protected、default默认public,不可以用其他的main方法可有,可运行不可有多继承继承一个类实现多个接口可以继承多个接口速度比接口快寻找在类中实现的方法添加新方法提供默认的实现必须改变实现接口的类// 抽象类与实体类 package packa; import packb.C; import packb.D; public class A implements C,D{ private String aa; public A() { //空构造 } public A(String aa) { this.aa = aa; } public void aaa() { System.out.println("实体类的方法。。。。"); } @Override public void dd() { System.out.println("实体类实现D接口的方法"); } @Override public void cc() { System.out.println("实体类实现C接口的方法"); } } package packa; import packb.C; import packb.D; public abstract class B extends A implements C,D{ private String bb; //抽象类的成员变量 public B(String aa) { //构造方法 super(aa); } public abstract void bbb(); //抽象方法 public void bbbb() { //默认方法实现 System.out.println("抽象类B的非抽象方法"); } public void cc() { System.out.println("实现的C接口"); } public void dd() { System.out.println("实现的D接口"); } } package packb; public interface C { public static final double PI = 3.14; public void cc(); } package packb; public interface D extends C{ public static final double PI = 3.22; // @Override // public void cc(); public void dd(); } package packb; public class E implements C,D{ //多重实现接口 @Override public void dd() { System.out.println("实现的C接口"); } @Override public void cc() { System.out.println("实现的D接口"); } }
一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。
实现多态的方式:继承和接口
1. 多态是方法的多态,不是属性(变量)的多态(多态与属性无关)。
2. 多态的存在要有3个必要条件:继承,方法重写,父类引用指向子类对象。
3. 父类引用指向子类对象后,用该父类引用调用子类重写的方法,此时多态就出现了。
总结:所谓封装,就是通过定义类并且给类的属性和方法加上访问控制来抽象事物的本质特性。所谓继承,就是代码重用,而多态,就是一个行为(方法)在不同对象上的多种表现形式。
package packs; import packa.A; import packa.B; import packb.C; public class theme { public static void main(String[] args) { C c = new A(); // 多态的提现,父类引用指向子类对象 c.cc(); } }说完面向对象的三大特征,有必要提一下最常说的重载与重写;
发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
发生在子类中,是子类对父类的允许访问的方法的实现过程进行重新编写,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。另外,私有方法(private修饰)不可被重写。一句话总结,方法提供的行为改变,方法的外貌没有改变
package packa; public class A{ //重载 private String aa; private int aaa; private double aaaa; private char a; public void aq(String as) { } public int aq(int ass,double asp) { return aaa; } public String aq(int psa,double spa,char ac) { return aa; } public double aq(String as,double asp,int psa,char spp) { return aaaa; } } package packa; public class A{ //重写 public void aq() { System.out.println("父类方法"); } } package packa; public class Aa extends A { @Override public void aq() { System.out.println("子类方法"); } }我们刚开始看到这三个东西,跟入门小白一样,恐怕只知道JDK包含JRE,JRE也包含JVM, 之前就曾有面试官问过这样的问题,问之前一脸懵逼,问之后无所不ji。。。开玩笑而已,入行之初,接触的就是这个东西。

看到这张JDK体系结构图,估计很多人是懵逼的,一开始看这种图,都是晕 的,多看几遍,说不定可以看出点什么道道。
JDK :Java SE Development Kit,java开发工具包,它提供了编译、运行Java程序所需的各种工具和资源,包括Java编译器、Java运行时环境,以及常用的Java基础的类库等。
JRE: Java Runtime Environment,顾名思义,java运行时环境,主要包含jvm 的标准实现和 Java 的一些基本类库。它相对于 jvm 来说,多出来的是一部分的 Java 类库。
JVM:Java Virtual Machine,我们常提到的java虚拟机,它是Java程序跨平台的关键部分,当使用Java编译器编译Java程序时,生成的是与平台无关的字节码,这些字节码只面向JVM。不同平台的JVM都是不同的,但它们都提供了相同的接口。

程序运行时,虚拟机类加载子系统会load程序的.class文件到虚拟机内存里面,并由执行引擎去执行程序,准确地说,jvm的组成分为3大块,类装载子系统、运行时数据区、执行引擎。我们所说的运行时数据区只是程序运行时,JVM工作的一方面。
当一个classloader加载一个类的时候,除非显示的使用另一个loader,该类所依赖的和引用的类也由这个Classloder载入。
先委托父类加载器寻找目标类,找不到的情况下下载自己的路径中查找并载入目标类。【加载一个类时,首先会先检查是否已经被加载过了,如没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载失败,则抛出ClassNotFoundException异常,在调用自己的findClass()方法进行加载。】
一层一层向上委托,当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成,每一个层次类加载都是如此,因此所有的加载请求都应该传送到启动类加载器中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径里找不到这个所需要加载的类),子类加载器才会尝试自己去加载。
当一个HelloWorld.class文件被加载时.不考虑自定义类加载器,首先会在AppClassLoader中检查是否已加载过,如果有就无需再加载.如果没有,那么会拿到父加载器,然后调用父加载器的loadClass().父类中同样会先检查自己是否已经加载过,如果没有再往上.直到到达BootstrapClassLoader之前,都是没有哪个加载器自己选择加载的.如果父加载器无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException.
优点
1:安全,可避免用户自己编写的类动态替换Java的核心类,如java.lang.String
2:避免全限定命名的类重复加载(使用了findLoadClass()判断当前类是否已加载)
这种设计有个好处是,如果有人想替换系统级别的类:String.在双亲委派机制下这些系统类已经被Bootstrap classLoader加载过了,不会再去加载,从一定程度上防止了危险代码的植入.
打破双亲委派机制则不仅要继承ClassLoader类,还要重写loadClass和findClass方法 。
关于Tomcat的类加载机制:
Tomcat的类加载机制并不遵循父委派模型。下图是Tomcat类加载器的结构:

1.CommonClassLoader能加载的类都可以被Catalina ClassLoader和SharedClassLoader使用,从而实现了公有类库的共用。
2.CatalinaClassLoader和Shared ClassLoader自己能加载的类则与对方相互隔离。
3.WebAppClassLoader可以使用SharedClassLoader加载到的类,但各个WebAppClassLoader实例之间相互隔离。
4.JasperLoader的加载范围仅仅是这个JSP文件所编译出来的那一个.Class文件,它出现的目的就是为了被丢弃:当Web容器检测到JSP文件被修改时,会替换掉目前的JasperLoader的实例,并通过再建立一个新的Jsp类加载器来实现JSP文件的HotSwap功能。
Tomcat违背了父委派模型
tomcat违背了父委派模型,因为双亲代理机制也就是父委派模型要求除了顶层启动类加载器之外,其余的类加载都应该由其父类加载器加载。而Tomcat不是这样实现的,Tomcat为了实现隔离性,没有遵循这个约定,每个WebappCLoader加载自己目录下的class文件,不会传递给父类加载器。

线程私有的,与线程在同一时间创建。管理JAVA方法执行的内存模型。每个方法执行时都会创建一个桢栈来存储方法的的变量表、操作数栈、动态链接方法、返回值、返回地址等信息。栈的大小决定了方法调用的可达深度(递归多少层次,或嵌套调用多少层其他方法,-Xss参数可以设置虚拟机栈大小)。栈的大小可以是固定的,或者是动态扩展的。如果请求的栈深度大于最大可用深度,则抛出stackOverflowError;如果栈是可动态扩展的,但没有内存空间支持扩展,则抛出OutofMemoryError。
堆里面的实例对象根据方法区里面的class对象创建出来的,虚拟机栈引用的对象是根据堆里面的实例对象来的。
局部变量表里面的一个引用,被另外一个引用类型指向堆里面的实例,它的引用计数器就+1,当它计数器为0时,证明可以被回收,会将它的标记状态由0改为1,证明它可以被回收。缺点是无法解决循环引用的问题。
通过一系列被称为“GC Roots”的对象作为起点,从这些节点向下搜索,节点走过的路径成为引用链,当一个对象到“GC Roots”没有任何引用链,证明它是没用的。
解决循环引用,是通过固定一些根节点,常见的例如【虚拟机栈的局部变量表、方法区的类静态属性引用的对象、方法区常量引用的对象、本地方法引用的对象】
没有任何一个对象是指向这个引用常量的,这时候它就是废弃常量,如果此时内存不够,它会被清理出常量池,如果内存足够,则 不需要清理。
1、该类所有实例都被回收,没任何引用。
2、加载这个类的classloader已经被回收。
3、该类对应的对象没在任何地方被引用,也没有任何通过反射区访问这个类的。
最好应用在Survivor区,刚好一分为二,from,to
垃圾收集器:
Serial(串行)收集器:新生代采用复制算法,老年代采用标记-整理算法。
应用程序线程,进行一次GC,之后将应用线程停掉,之前都是单线程去执行一个程序,没太多的线程资源,此时GC垃圾回收线程就专门执行GC,应用程序线程不能跑停掉了,会产生STW(Stop the world,无法解决的问题,停顿时间,即垃圾收集器做垃圾回收中断应用执行的时间,JVM调优指标之一),【假如你写了一个web端,此时JVM执行GC,web端卡个一两秒,用户体验特别不好】,只适用于程序简单,对并发要求也不高,可以考虑它,执行效率是比较高的。

应用程序线程运行期间产生GC,先进行初始标记不回收,等再次发生GC的时候再来进行下一步,进入到并发标记阶段,同时开启用户线程与GC线程,GC线程会对运行中产生的浮动垃圾【用户线程在运行的过程中还会产生一些垃圾】进行标记,标记之后进入下一个阶段。重新标记,此时将所有的线程都停掉进行专门标记,将所有产生浮动垃圾或者没注意到的垃圾都进行重新标记,结束之后进行到清理阶段,此时开始开启用户线程,标记阶段线程跑得比较快,找内存里面没用的对象是找的非常快的,因为只需要找标记状态,扫一遍,但不进行回收,一旦进行回收,它会变得慢起来,把用户线程启动,此时,用户线程与GC同时运行,对用户来说,此时STW是比较短暂的。最后一个步骤则是并发清除,用户线程开启,GC线程对标记的区域进行清除。一般来讲新生代的stw是比老年代的stw短暂很多。应用在老年代
优点:需要很多次回收,时间停顿短,清理慢,把多次停顿做了一个分解。并发收集
缺点:
1、对CPU资源敏感
2、没有办法处理浮动垃圾
3,使用标记清除算法,导致收集结束时产生大量空间碎片。
接下来介绍最热的G1回收器
堆区域分代,但G1不分代,分块,把内存分成一块一块的,Region区域,随机把有一些区域设为Eden,如果你的对象是比较小的,那找一块小的区域放进去即可;如果你的对象比较大,存活时间比较长,找一个比较大点的内存空间放进去,这个时候它就会变成Old区域。

并行与并发:充分利用CPU、多核环境下硬件优势,发挥每一个CPU核心的作用,来缩短STW停顿时间。
分代手机:从整体来看基于标记-整理算法,从局部来看是基于复制算法。
可预测停顿:对我们的JVM设置一个参数,比如说G1过程的延时,可以设置为10ms,即每一次垃圾收集的过程都会在10ms内完成,但是它的次数会增多。
初始标记
并发标记
最终标记
筛选回收:在Region区域做一个优先级的设置,比如说这个区域某对象占比几百M,其他对象占比几百K,这个时候该对象会被标记为可回收对象,它就会被优先回收掉,因为回收它的价值是最大的。筛选回收就是为了实现可预测的停顿。
假如在10ms回收我们的内存,本来时间是1s回收,现在就有很多对象回收不了,这个时候会进行垃圾回收筛选,将优先列表里面最优先级别的Region区域回收掉,这也是为什么G1称之为Garbage-First了。
怎么选择垃圾收集器?
1.优先调整堆的大小让服务器自己选择
2.如果服务器单核,没有停顿时间的要求,串行或者JVM自选
3.如果允许停顿时间超过1s,并行或者JVM自选
4.如果内存小于100M,选串行收集器。
5.如果响应时间最重要,不能超过1s,选并发收集器
上一篇:java 面试 大全
下一篇:java基础学习日记(10)
爱鸽者手机版下载v3.2.9 安卓版
243.57MB |商务办公
一品威客网接单app(一品众包)下载v2.7.1 安卓最新版
55.01MB |商务办公
诸葛找房网官方版下载v4.8.1.1 安卓最新版
66.6MB |生活服务
皓盘云建最新版下载v9.0 安卓版
53.38MB |商务办公
ris云客移动销售系统最新版下载v1.1.25 安卓手机版
42.71M |商务办公
粤语翻译帮app下载v1.1.1 安卓版
60.01MB |生活服务
人生笔记app官方版下载v1.19.4 安卓版
125.88MB |系统工具
萝卜笔记app下载v1.1.6 安卓版
46.29MB |生活服务
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-03-26
2022-02-15
2022-02-14