JAVASE第七式


先处理小的异常,再处理大的异常.若大的异常放前面,小的异常永远不会触发

ArithmeticException 	是算数异常
NumberFormatException 是数据格式异常
Exception 						异常
ArrayIndexOutOfBoundException 数组索引超过界限异常

先处理具体的异常,如果没有则放到一个大的范围之中Exception

私有:java虚拟机栈,程序计数器,本地方法栈

共享:java堆,方法区


修饰非静态方法,锁的是this对象 修饰静态方法,锁的是class对象


小范围转化为大范围的数值型变量,jvm在进行编译的过程中将进行类型的自动提升

大范围到小范围会丢失精度

范围大小依次是:byte、char、short、int、long、float、double

byte     1字节 
char     2字节 
short    2字节 
int      4字节 
float    4字节 
long     8字节 
double ``8字节 

JAVA的初始化顺序:

父类的静态成员初始化>父类的静态代码块>子类的静态成员初始化>子类的静态代码块>父类的代码块>父类的构造方法>子类的代码块>子类的构造方法

注意:

1.静态成员和静态代码块只有在类加载的时候执行一次,再次创建实例时,不再执行,因为只在方法区存在一份,属于一整个类。

2.上述的是通用的加载顺序,如果没有则省略


A.Java系统提供3种类加载器:

启动类加载器(Bootstrap ClassLoader)

扩展类加载器(Extension ClassLoader)

应用程序类加载器(Application ClassLoader)

B.《深入理解Java虚拟机》P228:对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器都拥有一个独立的类名称空间

这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那么这两个类必定不相等

接口类是一种特殊类,因此对于同一接口不同的类装载器装载所获得的类是不相同的。B错误

C.类只需加载一次就行,因此要保证类加载过程线程安全,防止类加载多次。C正确

D. Java程序的类加载器采用双亲委派模型,实现双亲委派的代码集中在java.lang.ClassLoader的loadClass()方法中,此方法实现的大致逻辑是:先检查是否已经被加载,若没有加载则调用父类加载器的loadClass()方法若父类加载器为空则默认使用启动类加载器作为父类加载器如果父类加载失败,抛出ClassNotFoundException异常。D错误

E.双亲委派模型的工作过程:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。E正确

F.应用程序类加载器(Application ClassLoader)负责加载用户类路径(ClassPath)上所指定的类库,不是所有的ClassLoader都加载此路径。F错误

Java语言系统自带有三个类加载器: 
- Bootstrap ClassLoader 最顶层的加载类,
主要加载核心类库,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。
另外需要注意的是可以通过启动jvm时指定-Xbootclasspath和路径来改变Bootstrap ClassLoader
的加载目录。比如java -Xbootclasspath/a:path被指定的文件追加到默认的bootstrap路径中。
我们可以打开我的电脑,在上面的目录下查看,看看这些jar包是不是存在于这个目录。 
  
- Extention ClassLoader 扩展的类加载器,加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件。
还可以加载-D java.ext.dirs选项指定的目录。 
  
- Appclass Loader也称为SystemAppClass 加载当前应用的classpath的所有类。

加载顺序:
1. Bootstrap CLassloder 
2. Extention ClassLoader 
3. AppClassLoader

1.Statement、PreparedStatement和CallableStatement都是接口(interface)。
    
2.Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自
PreparedStatement。 


Statement接口提供了执行语句和获取结果的基本方法; 
PreparedStatement接口添加了处理 IN 参数的方法; 
CallableStatement接口添加了处理 OUT 参数的方法。 

a.Statement: 
普通的不带参的查询SQL;支持批量更新,批量删除; 

b.PreparedStatement: 
可变参数的SQL,编译一次,执行多次,效率高; 
安全性好,有效防止Sql注入等问题; 
支持批量更新,批量删除; 

c.CallableStatement: 
继承自PreparedStatement,支持带参数的SQL操作; 
支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持; 

Statement每次执行sql语句,数据库都要执行sql语句的编译 , 
最好用于仅执行一次查询并返回结果的情形,效率高于PreparedStatement。 

PreparedStatement是预编译的,使用PreparedStatement有几个好处 
1. 在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL
当然会比多次编译一条SQL的效率要高。 
2. 安全性好,有效防止Sql注入等问题。 
3. 对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用
   batch; 
4. 代码的可读性和可维护性

数组的初始化:静态初始化和动态初始化

静态初始化,不能指定容量,动态初始化,必须指定容量


由于arr[0] =0,所以在进入 test()方法里面会在第一个if 上抛出一个 NullPointerException,

接着会执行 finally 的语句,

(finally语句先于 return 和 throw语句执行),输出一个'e',然后回到 main方法中

由于捕捉到异常,所以进入到catch语句中,然后打印一个'E',所以最终结果为"eE"


首先运行这个程序,在c/c++和java会发现不一样,在c/c++中答案是1,在java中答案是0。为什么呢?

原因:jvm里面有两个存储区,一个是暂存区(是一个堆栈,以下称为堆栈),另一个是变量区

jvm会这样运行这条语句, JVM把count值(其值是0)拷贝到临时变量区

步骤2 count值加1,这时候count的值是1

步骤3 返回临时变量区的值,注意这个值是0没修改过

步骤4 返回值赋值给count,此时count值被重置成0

c/c++中没有另外设置一个临时变量或是临时空间来保存i,所有操作都是在一个内存空间中完成的,所以在c/c++中是1

如果你理解JVM的内存模型,就不难理解为什么答案返回的是0,而不是1。
我们单独看问题中的这两句代码。

int i = 0; i = i++;
Java虚拟机栈(JVM Stack)描述的是Java方法执行的内存模型,而JVM内存模型是基于“栈帧”的,
每个栈帧中都有 局部变量表 和 操作数栈 (还有动态链接、return address等),
那么JVM是如何执行这个语句的呢?通过javap大致可以将上面的两行代码翻译成如下的JVM指令执行代码。
0: iconst_0
1: istore_1
2: iload_1
3: iinc          1, 1
6: istore_1
7: iload_1

接下来分析一下JVM是如何执行的:
第0:将int类型的0入栈,就是放到操作数栈的栈顶
第1:将操作数栈栈顶的值0弹出,保存到局部变量表 index (索引)值为1的位置。
(局部变量表也是从0开始的,0位置一般保存当前实例的this引用,当然静态方法例外,
因为静态方法是类方法而不是实例方法)
第2:将局部变量表index 1位置的值的副本入栈。(这时局部变量表index为1的值是0,操作数栈顶的值也是0)
第3:iinc是对int类型的值进行自增操作,后面第一个数值1表示,局部变量表的index值,
说明要对此值执行iinc操作,第二个数值1表示要增加的数值。
(这时局部变量表index为1的值因为执行了自增操作变为1了,但是操作数栈中栈顶的值仍然是0)
第6:将操作数栈顶的值弹出(值0),放到局部变量表index为1的位置(旧值:1,新值:0),
覆盖了上一步局部变量表的计算结果。
第7:将局部变量表index 1位置的值的副本入栈。(这时局部变量表index为1的值是0,操作数栈顶的值也是0)

总结:从执行顺序可以看到,这里第1和第6执行了2次将0赋值给变量i的操作(=号赋值),
i++操作是在这两次操作之间执行的,自增操作是对局部变量表中的值进行自增,而栈顶的值没有发生变化,
这里需要注意的是保存这个初始值的地方是操作数栈而不是局部变量表,最后再将栈顶的值覆盖到局部变量
表i所在的索引位置中去。

有兴趣的同学可以去了解一下JVM的栈帧(Stack Frame)

关于第二个陷阱(为什么 fermin方法没有影响到i的值 )的解答看下面。

inc.fermin(i);
1. java方法之间的参数传递是 值传递 而不是 引用传递
2. 每个方法都会有一个栈帧,栈帧是方法运行时的数据结构。这就是说每个方法都有自己独享的局部变量表。
(更严谨的说法其实是每个线程在执行每个方法时都有自己的栈帧,或者叫当前栈帧 current stack frame)
3. 被调用方法fermin()的形式参数int i 实际上是调用方法main()的实际参数 i 的一个副本。
4. 方法之间的参数传递是通过局部变量表实现的,main()方法调用fermin()方法时,传递了2个参数:
第0个隐式参数是当前实例(Inc inc = new Inc(); 就是inc引用的副本,引用/reference 是指向对象
的一个地址,32位系统这个地址占用4个字节,也就是用一个Slot来保存对象reference,这里传递的实际上
是reference的一个副本而不是 reference本身 );

如果main()方法和fermin()方法共享局部变量表的话,那答案的结果就会有所不同。 
其实你自己思考一下,就会发现, JVM虚拟机团队这么设计是有道理的。

以后再遇到这种题直接把++去掉,错了算我的

比如:

int i=0;i=i++;i=i=0;

i=i+++100;i=i+100=100;


i ++ ; //是先取值再 ++

++ i; //是先++ 再取值


ABC在java中会报错,D可以正常运行, 所以答案是ABC.

A. 'a'是字符,' a'这个是空格和a,必须要用" a"才可以;

B.String有length()方法

C.int 无法直接转成String类型

D.尾部添加字符串”100


当一个实力类集成了一个抽象类,必须实现抽象类中的抽象方法,抽象类本身没有错误,但是cat类编译通不过



HttpServlet容器响应Web客户请求流程如下:

1)Web客户向Servlet容器发出Http请求;

2)Servlet容器解析Web客户的Http请求;

3)Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息;

4)Servlet容器创建一个HttpResponse对象;

5)Servlet容器调用HttpServlet的service方法,这个方法中会根据request的Method来判断具体是执行doGet还是doPost,把HttpRequest和HttpResponse对象作为service方法的参数传给HttpServlet对象;

6)HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;

7)HttpServlet调用HttpResponse的有关方法,生成响应数据;

8)Servlet容器把HttpServlet的响应结果传给Web客户。

doGet()或doPost()是创建HttpServlet时需要覆盖的方法

Servlet生命周期分为三个阶段:

1.初始化阶段  				调用init()方法

2.响应客户请求阶段  调用service()方法

3.终止阶段  				调用destroy()方法


java中的线程安全是什么:
就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问


什么叫线程安全:
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。


线程安全问题都是由全局变量及静态变量引起的。
若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的

若有多个线程同时执行写操作,一般都需要考虑线程同步,否则就可能影响线程安全。
看过vector源码的同学就会知道他的许多操作都是加了synchronized修饰的比如他的添加元素。(不知道synchronized是什么意思的自行百度!)

Properties类表示一组持久的属性。Properties可以保存到流中或从流中加载。 
属性列表中的每个键及其对应的值都是一个字符串。
属性列表可以包含另一个属性列表作为其“默认值”; 如果在原始属性列表中找不到属性键,
则会搜索此第二个属性列表。

因为Properties从继承Hashtable时,put种putAll方法可应用于Properties对象。 
强烈不鼓励使用它们,因为它们允许调用者插入其键或值不是Strings。 应该使用setProperty方法。 
如果store或save方法在包含非String键或值的“受损害”Properties对象上调用,则调用将失败。 
类似地,如果在包含非String密钥的“受损害”Properties对象上调用propertyNames或list方法的调用将失败

面向字符输入流类都是Reader的子类:

面向字符的输出流都是类Writer的子类


先分析一下里面各个参数的含义: 
-Xms:1G , 就是说初始堆大小为1G 
-Xmx:2G , 就是说最大堆大小为2G 
-Xmn:500M ,就是说年轻代大小是500M(包括一个Eden和两个Survivor) 
-XX:MaxPermSize:64M , 就是说设置持久代最大值为64M 
-XX:+UseConcMarkSweepGC , 就是说使用使用CMS内存收集算法 
-XX:SurvivorRatio=3 , 就是说Eden区与Survivor区的大小比值为3:1:1
题目中所问的Eden区的大小是指年轻代的大小,直接根据-Xmn:500M	和		-XX:SurvivorRatio=3
可以直接计算得出
500M*(3/(3+1+1)) 
=500M*(3/5) 
=500M*0.6 
=300M  
所以Eden区域的大小为300M

public		可以被当前类,子类,包,其他包访问,
protected 可以被当前类,子类,包访问
default		可以被可以被当前类,包内访问;
private		只能被当前类访问

管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动而且只能在具有亲缘关系的进程间使用

进程的亲缘关系通常是指父子进程关系。


链接:https://www.nowcoder.com/questionTerminal/687a87f9018e4ba4a747ff31ffbcd9c9
来源:牛客网

Collection

    -----List

               -----LinkedList    非同步

                ----ArrayList      非同步,实现了可变大小的元素数组

                ----Vector          同步           

    -----Set   不允许有相同的元素

 Map

    -----HashTable        同步,实现一个key--value映射的哈希表,key和value都不允许出现null值

    -----HashMap          非同步,

    -----WeakHashMap      改进的HashMap,实现了“弱引用”,如果一个key不被引用,则被GC回收
注:
List接口中的对象按一定顺序排列,允许重复 
Set接口中的对象没有顺序,但是不允许重复 
Map接口中的对象是key、value的映射关系,key不允许重复

&按位与,| 按位或,~按位取反,!逻辑取反

逻辑取反:将所有非0的数值看做是1,将1变为0,将0变为1.

按位取反:将二进制数值的每一位的0变为1,1变为0.


外部类:public 、default
内部类:public 、privite、protect
局部类:无

public class Base
{
   public void methodOne()
   {
      System.out.print("A");
      methodTwo();
   }

   public void methodTwo()
   {
      System.out.print("B");
   }
}

public class Derived extends Base
{
   public void methodOne()
   {
      super.methodOne();
      System.out.print("C");
   }

   public void methodTwo()
   {
      super.methodTwo();
      System.out.print("D");
   }
}

只要是被子类重写的方法,不会被super调用都是调用子类的方法

知识点:1.多态中成员方法使用规则 编译看左边,运行看右边

2.多态中,子类重写的方法,当super调用就是调用父类方法


A、子类的构造器第一行默认都是super(),默认调用直接父类的无参构造,一旦直接父类没有无参构造,

那么子类必须显式的声明要调用父类 或者自己的哪一个构造器。

BC、接口只能继承接口,但是可以多继承。类都是单继承,但是继承有传递性。

D、一个类一旦没有显式的定义任何构造,那么JVM会默认给你一个无参构造。无参构造的第一行依然默认是super()。



通过继承,子类可以拥有所有父类对其可见的方法和域

A.私有方法只能在本类中可见,故不能继承,A错误

B.缺省访问修饰符只在本包中可见,在外包中不可见,B错误

C.保护修饰符凡是继承自该类的子类都能访问,当然可被继承覆盖;C正确

D.static修饰的成员属于类成员,父类字段或方法只能被子类同名字段或方法遮蔽,不能被继承覆盖,D错误
------------------------------------------------------------------------------------------------------------------

应该是:public>protected>默认(包访问权限)>private,因为protected除了可以被同一包访问,还可以被包外的子类所访问


A,Object是所有类的直接或者间接父类。

B,接口没有继承Object类。(一旦继承,Object中可以有实例方法的

C,Object的equals方法,只有一句话,return this==object。这句话说反了。

D,和A一样,都是Object的子类了,肯定有Object的方法:hashCode、equals、toString、clone、notify、notifyall、wait、finalize、getClass


list集合是有序可重复 set集合是无序不可重复


1反射机制是什么

反射机制是在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法

对于任意一个对象,都能够调用它的任意一个方法和属性;

这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

2反射机制能做什么

反射机制主要提供了以下功能:

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;
  • 生成动态代理。


abstract修饰的类是抽象类,是可以继承的,而final修饰的类表示不能再被继承,故肯定不能共同使用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值