java盲点(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_31433525/article/details/80251199

java盲点(一)

函数的调用过程

调用某个函数实际上将程序执行顺序转移到该函数所存放在内存中某个地址,将函数的程序内容执行完后,再返回到
转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保
存地址继续执行。也就是通常说的压栈和出栈。因此,函数调用要有一定的时间和空间方面的开销。那么对于那些函数体
代码不是很大,又频繁调用的函数来说,这个时间和空间的消耗会很大。

内联函数

在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。
但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要非常注意的是对递归函数的内联扩展可能带来部分编译器的无穷编译。
C、C++中可以声明内联函数,在java中不支持直接声明,但是jvm会根据情况进行优化内联。

内联函数特点

(1)提升效率。如上说明。
(2)占更多内存空间。编译器直接将内联函数扩展开,调用多复制品就多,因此更占用内存。
(3)java中不需额外关注,jvm会自动进行优化
void main() { ….. a = max (x, y);
// 内联,等价于 “a = (x > y ? x : y);” 直接扩展开了,不再调用方法 ….. }

使用final方法原因

一、锁定方法。防止任何继承类修改、覆盖
二、效率。在java早期实现中,如果将一个方法指明为final,就是同意编译器将针对该方法的调用都转化为内嵌调用。…..

修饰符作用

public 可以被任何类访问
protected 可以被同一包中的所有类访问可以被所有子类访问 子类没有在同一包中也可以访问
private 只能够被 当前类的方法访问
缺省无访问修饰符 可以被同一包中的所有类访问 如果子类没有在同一个包中,也不能访问

比较

是比较地址值是否相等,.equals()方法是比较值是否相等

构造方法

构造方法是一种特殊的方法,一个类可以不定义构造方法,在这种情况下,类中隐含定义一个方法体为空的无参构造方法。这个构造方法称为默认构造方法,当且仅当类中没有明确定义任何构造方法时才会自动提供它。可见性修饰符方面,使用private也是可以的,能有一些特殊的作用比如在单例模式下。
(1)方法名必须与类名相同;
(2)不要声明返回类型;
(3)不能被static、final、synchronized、abstract和native修饰;
(4)构造方法用final和abstract修饰没有意义。

文件后缀

.class 编译后的Java文件
.java是未编译的程序
.jsp是页面程序
.xml配置程序
.jar是.calss的集合
java中源文件的后缀为.java,经过javac.exe编译后生成字节码文件,后缀为.class,再经过java.exe编译为可执行文件,后缀为.exe。

“|”与”||”的区别

“|”是按位或:先判断条件1,不管条件1是否可以决定结果(这里决定结果为true),都会执行条件2
“||”是逻辑或:先判断条件1,如果条件1可以决定结果(这里决定结果为true),那么就不会执行条件2

Integer和int的比较

Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值小于等于127并且大于等于-128时才可使用常量池,因为他们至占用一个字节(-128~127);
Integer.valueOf方法中如果传递的整型变量>= -128并且小于127时会返回IntegerCache类中一个静态数组中的某一个对象, 否则会返回一个新的Integer对象,代码如下
123456 public static Integer valueOf(int i) {assert IntegerCache.high >= 127;if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
①无论如何,Integer与new Integer不会相等。不会经历拆箱过程,
②两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false
java在编译Integer i2 = 128的时候,被翻译成-> Integer i2 = Integer.valueOf(128);而valueOf()函数会对-128到127之间的数进行缓存
③两个都是new出来的,都为false
④int和integer(无论new否)比,都为true,因为会把Integer自动拆箱为int再去比。

真数组

数组元素在内存中是一个接着一个线性存放的,通过第一个元素就能访问随后的元素,这样的数组称之为“真数组”。,避免了数据覆盖的可能性,和数据类型覆盖并没有关系。实现了真数组为Java语言健壮性的特点之一

Servlet 与 CGI 的比较

和CGI程序一样,Servlet可以响应用户的指令(提交一个FORM等等),也可以象CGI程序一样,收集用户表单的信息并给予动态反馈(简单的注册信息录入和检查错误)。
然而,Servlet的机制并不仅仅是这样简单的与用户表单进行交互。传统技术中,动态的网页建立和显示都是通过CGI来实现的,但是,有了Servlet,您可以大胆的放弃所有CGI(perl?php?甚至asp!),利用Servlet代替CGI,进行程序编写。
对比一:当用户浏览器发出一个Http/CGI的请求,或者说 调用一个CGI程序的时候,服务器端就要新启用一个进程 (而且是每次都要调用),调用CGI程序越多(特别是访问量高的时候),就要消耗系统越多的处理时间,只剩下越来越少的系统资源,对于用户来说,只能是漫长的等待服务器端的返回页面了,这对于电子商务激烈发展的今天来说,不能不说是一种技术上的遗憾。
而Servlet充分发挥了服务器端的资源并高效的利用。每次调用Servlet时并不是新启用一个进程 ,而是在一个Web服务器的进程敏感词享和分离线程,而线程最大的好处在于可以共享一个数据源,使系统资源被有效利用。
对比二:传统的CGI程序,不具备平台无关性特征,系统环境发生变化,CGI程序就要瘫痪,而Servlet具备Java的平台无关性,在系统开发过程中保持了系统的可扩展性、高效性。
对比三:传统技术中,一般大都为二层的系统架构,即Web服务器+数据库服务器,导致网站访问量大的时候,无法克服CGI程序与数据库建立连接时速度慢的瓶颈,从而死机、数据库死锁现象频繁发生。而我们的Servlet有连接池的概念,它可以利用多线程的优点,在系统缓存中事先建立好若干与数据库的连接,到时候若想和数据库打交道可以随时跟系统”要”一个连接即可,反应速度可想而知。
CGI不可移植,为某一特定平台编写的CGI应用只能运行于这一环境中。每一个CGI应用存在于一个由客户端请求激活的进程中,并且在请求被服务后被卸载。这种模式将引起很高的内存、CPU开销,而且在同一进程中不能服务多个客户

静态语句块

public class Test{
static{
   int x=5;
}
static int x,y;
public static void main(String args[]){
   x--;
   myMethod( );
   System.out.println(x+y+ ++x);
}
public static void myMethod( ){
  y=x++ + ++x;
 }
}

1.JVM加载class文件时,就会执行静态代码块,静态代码块中初始化了一个变量x并初始化为5,由于该变量是个局部变量,静态代码快执行完后变被释放。
2.申明了两个静态成员变量x,y,并没有赋初值,会有默认出值,int类型为0,
3.执行x–操作,变量单独进行自增或自减操作x–和–x的效果一样,此时x变为了-1
4.调用MyMethod()方法,在该方法中对x和y进行计算,由于x和y都是静态成员变量,所以在整个类的生命周期内的x和y都是同一个
5.y=x++ + ++x可以看成是y=(x++)+(++x),当++或者–和其它变量进行运算时,x++表示先运算,再自增,++x表示先自增再参与运算
所以就时x为-1参与运算,然后自增,x此时为0,++x后x为1,然后参与运算,那么y=-1+1就为0,此时x为1
6.执行并打印x+y + ++x运算方式和第5步相同,最后计算结果就为3.

频繁进出try-catch,但没有异常,对性能有影响吗

会,try块会阻止java的优化。参考

synchronized关键词修饰

类的成员方法若用synchronized关键词修饰,将会使用方法作为锁的对象。
类的静态方法若用synchronized关键词修饰,将会使用类作为锁的对象。

volatile的作用

保持内存可见性和防止指令重排序参考

string,stringBuffer,stringBuilder的区别

string是不可改变的对象,每次修改都是重新创建一个string对象。
stringBuffer,可以对对象本身进行操作,是线程安全的。StringBuffer只能通过构造函数创建
stringBuilder,是strngBuffer的简易使用,是线程不安全的,单线程使用。strigBuilder>stringBuffer

include< > 和 #include” ” 的区别

include< > 引用的是编译器的类库路径里面的头文件。
include” ” 引用的是你程序目录的相对路径中的头文件

sleep()和wait()的异同

Java中的多线程是一种抢占式的机制,而不是分时机制。抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行。
共同点 :
1.他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。
2.wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。
需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。
不同点 :
1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。
sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
4.sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
5.wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态

文件编译

c文件经编译后生成exe文件。
java文件经编译后生成字节码文件即class文件,运行时字节码变成机器码,由cpu执行。
c/c++经编译生成机器码

static和final

static是静态修饰关键字,可以修饰变量和程序块以及类方法:当你定义一个static的变量的时候jvm会将将其分配在内存堆上,所有程序对它的引用都会指向这一个地址而不会重新分配内存;修饰一个程序块的时候(也就是直接将代码写在static{…}中)时候,虚拟机就会优先加载静态块中代码,这主要用于系统初始化;当修饰一个类方法时候你就可以直接通过类来调用而不需要新建对象。

final可以修饰变量、方法及类,当你定义一个final变量时,jvm会将其分配到常量池中,程序不可改变其值;当你定义一个方法时,改方法在子类中将不能被重写;当你修饰一个类时,该类不能被继承

猜你喜欢

转载自blog.csdn.net/qq_31433525/article/details/80251199