JAVASE 第四式


new出来的都是存放在堆内存的,Java中有常量优化机制。


主要考核了这几个知识点:

1.静态内部类才可以声明静态方法

2.静态方法不可以使用非静态变量

3.抽象方法不可以有函数体


链接:以下哪种JAVA的变量表达式使得变量a和变量b具有相同的内存_用友笔试题_牛客网
来源:牛客网
 

首先结论:

(1)int与Integer、new Integer()进行==比较时,结果永远为true

(2)Integer与new Integer()进行==比较时,结果永远为false

(3)Integer与Integer进行==比较时,看范围;在大于等于-128小于等于127的范围内为true,在此范围外为false。

下面是解析过程:

1.Integer与int比较时,Integer会有拆箱的过程,我们可以看看拆箱的代码:

直接返回的就是value,因此int与Integer以及new Integer()进行 ==比较时结果都是true。

2.Integer a=n时,如果n大于等于-128小于等于127时,会直接从IntegerCache中取,不在这个范围内,会new一个对象,所以Integer与new Integer进行 ==比较时,结果都是false。

3.Integer与Integer比较,需要看范围,如果在-128~127(包含-128,不包含127)范围内,因为都是从IntegerCache中取值,所以相等;若不在这个范围内,则都要去new一个对象,所以结果为false。


JVM中有JAVA虚拟机栈,栈帧。堆,程序计数器(也就是题目中所谓的PC寄存器),本地方法栈,方法区



接口体现的是一种规范和实现分离的设计哲学,代码编写过程中充分利用接口可以很大程度的降低程序各个模块之间的耦合,从而提高系统的可扩展性和可维护性。基于这一原则,很多软件架构更提倡面向接口编程而不是实现类编程。

接口和抽象类都可以被声明使用。

抽象类到底能不能被实例化是初学者很容易犯的错误,

抽象类确实有构造方法,但这个构造方法是用来被子类调用的,因为任何子类都必须调用从Object开始的所有父亲的构造方法,才算完成初始化工作。

如果抽象类被实例化,就会报错,编译无法通过。而接口里不包含构造器,自然无法被实例化。选项C正确。


JVM内存可以简单分为三个区:

1.堆区(heap): 用于存放所有对象,是线程共享的(数组也属于对象)

2.栈区(stack): 用于存放基本数据类型的数据和对象的引用,是线程私有的(分为:虚拟机栈和 本地方法栈

3.方法区(method): 用于存放类信息、常量、静态变量、编译后的字节码等,是线程共享的(也别称为非堆,即None-Heap)

方法调用时,会创建栈帧在栈中,调用完是程序自动出栈释放,而不是GC释放。Java中的垃圾回收器GC主要针对的是堆区。所以在栈区中的方法调用就不会由GC释放


class X{
	Y y=new Y();
	public X(){
		System.out.print("X");
	}
}
class Y{
	public Y(){
		System.out.print("Y");
	}
}
public class Z extends X{
	Y y=new Y();
	public Z(){
		System.out.print("Z");
	}
	public static void main(String[] args) {
		new Z();
	}
}

初始化过程:

1.初始化父类中的静态成员变量和静态代码块

2.初始化子类中的静态成员变量和静态代码块

3.初始化父类的普通成员变量和代码块,再执行父类的构造方法

4.初始化子类的普通成员变量和代码块,再执行子类的构造方法;

(1)初始化父类的普通成员变量和代码块,执行 Y y=newY(); 输出Y

(2)再执行父类的构造方法;输出X

(3)初始化子类的普通成员变量和代码块,执行 Y y=new Y(); 输出Y

(4)再执行子类的构造方法;输出Z

所以输出YXYZ


A、接口与抽象类是不同的概念。抽象类是用于捕捉子类的通用特性接口是抽象方法的集合

B、 实现接口必须实现接口的所有方法;

C 、接口可以继承一个或多个接口,抽象类只能继承一个类或者实现多个接口;

D、 一个类只能继承一个类,但是可以实现多个接口。


javac将源代码编译成class文件,字节码, java将字节码编译成机器码,exe程序


Socket套接字,就是源端口号和目标端口号的组合 
 服务器端:ServerSocket提供的实例 
   ServerSocket server = new ServerSocket(端口号) 
 客户端,Socket提供的实例 
 Socket soc = new Socket(ip地址,端口号)

getParameter()是获取POST/GET传递的参数值;
getInitParameter获取Tomcat的server.xml中设置Context的初始化参数

getAttribute()是获取对象容器中的数据值;
getRequestDispatcher是请求转发。

静态变量只能在类中定义, 不能在方法中定义静态变量


A.一个类可以有多个构造方法,实际上就是方法的重载,正确

重载的要求是:方法名称必须相同。参数列表必须不同(个数不同、或类型不同、参数类型排列顺序不同)
对返回值没有做要求

B.用final修饰的类不能被继承,方法不能被覆盖,正确

C.如果没有构造方法,编译器会自动添加一个空参构造方法,错误

D.由源码可知,数组内部采用字符数组存储,该字符数组用final修饰,长度一旦确定不可再变,正确


在类方法中不能有this关键字,

,直接调用类方法即可,A错误,

B正确,在类方法中可以通过创建实例对象调用类的实例方法,C\D错误


LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。

Nginx ("engine x") 是一个高性能的 HTTP 和 反向*** 服务器,也是一个 IMAP/POP3/SMTP ***服务器。
Lighttpd 是一个德国人领导的开源Web服务器软件,其根本的目的是提供一个专门针对高性能网站,安全、快速、兼容性好并且灵活的web server环境。具有非常低的内存开销、cpu占用率低、效能好以及丰富的模块等特点。
Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。


Java接口中的方法默认被public abstract修饰,

而重写的其中一个要求就是重写方法的访问级别不小于原方法。因此,答案中只有C选项符合


Servlet生命周期分成3个阶段:

1)初始化阶段:调用init方法
2)响应客户请求:调用service
3)终止:调用destory方法

 
初始化阶段:在下列时刻servlet容器装载servlet

1  servlet容器启动时,自动装载某些servlet
2  在servlet容器启动后,客户首次向servlet发送请求
3  servlet类文件被更新之后,重新装载servlet


Servlet被装载之后,servlet容器创建一个servlet'对象并调用servlet的init方法,
在servlet生命周期内,init方法只能被调用一次。servlet工作原理:客户端发起一个请求,
servlet调用service方法时请求进行响应,service对请求的方式进行了匹配,
选择调用dopost或者doget等这些方法,然后进入对应方法中调用逻辑层的方法,实现对客户的响应。


响应客户请求:对于用户到达servlet的请求,servlet容器会创建特定于该请求的servletrequest
和servletresponse对象,然后调用servlet的service方法,service方法从servletrequest对象中
获取客户请求的信息,处理该请求,并且通过servletresponse对象向客户端返回响应信息。

 
终止:当web应用终止或者servlet容器终止或servlet容器重新装载servlet新实例时,servlet容器会调
用servlet对象的destory方法,在destory方法中可以释放servlet占用的资源


 

A.程序计数器是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的信号指示器(偏移地址),Java编译过程中产生的字节码有点类似编译原理的指令,程序计数器的内存空间存储的是当前执行的字节码的偏移地址,每一个线程都有一个独立的程序计数器(程序计数器的内存空间是线程私有的),因为当执行语句时,改变的是程序计数器的内存空间,因此它不会发生内存溢出 ,并且程序计数器是jvm虚拟机规范中唯一一个没有规定 OutOfMemoryError 异常 的区域;

B.java虚拟机栈:线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会床创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行结束,就对应着一个栈帧从虚拟机栈中入栈到出栈的过程。 没有类信息,类信息是在方法区中

C.java堆:对于绝大多数应用来说,这块区域是 JVM 所管理的内存中最大的一块。线程共享,主要是存放对象实例和数组

D.方法区:属于共享内存区域,存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。


方法重载(overload):

1.必须是同一个类

2方法名(也可以叫函数)一样

3参数类型不一样或参数数量不一样

方法的重写(override)两同两小一大原则:

方法名相同,参数类型相同

子类返回类型小于等于父类方法返回类型,

子类抛出异常小于等于父类方法抛出异常,

子类访问权限大于等于父类方法访问权限。

方法重载:同一类中的相同的方法名,参数和返回值均可不同。
方法重写:之类对父类已经实现的方法重新定义。


\

float 要加 f,int类型可以自动装箱成Integer,也可以向上转型为double,但是不能值转成Double。(不同的数据类型)


编译时异常必须显示处理,运行时异常交给虚拟机。

运行时异常可以不处理。当出现这样的异常时,总是由虚拟机接管。比如我们从来没有人去处理过Null Pointer Exception异常,它就是运行时异常,并且这种异常还是最常见的异常之一。出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,整个程序也就退出了。运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往不对它处理罢了。也就是说,如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止


request.getAttribute()方法返回request范围内存在的对象,

request.getParameter()方法是获取http提交过来的数据。

getAttribute是返回对象,getParameter返回字符串


set不能有重复的元素且是无序的,要有空值也就只能有一个,因为他不允许有重复

List可以有重复的元素且是有序的,要有空值也可以有多个,因为他允许重乎


不是局部变量在该方法被执行/调用时创建,而是应该为在该变量被声明并赋值时创建

可以理解为“当代码执行到该变量被赋值的代码时 才被创建

栈会为每个方法在运行的时候分配一块独立的 栈帧 内存区域

栈帧又包含“局部变量表”、“操作数栈”、“动态链接”以及“方法出口”四个部分


abstract类不能与final,static使用,final修饰方法,子类可以调用,但是不能覆盖

最好不要有private,因为私有和抽象放在一起,子类如果想要重写父类的私有方法根本继承不过来,也就无法重写

抽象类中可以有非抽象方法

抽象类中的可以都是非抽象的,但是抽象方法一定要在类和接口中


public static void main(String args[]) {
		Thread t=new Thread(){
		public void  run(){
			dianping();
			
		}
	};
	t.start();
	System.out.print("dazhong");
	}
	static void dianping(){
		System.out.print("dianping");
}

上面的main()方法中,并没有创建一个新的线程,只是简单的方法调用,如果想要创建线程,需要t.start();

创建线程,等待CPU时间片,而run()方法只是简单地方法调用

所以先执行run()方法,在输出 dazhong


编码格式由浏览器决定,

浏览器根据html中指定的编码格式进行编码,tomcat根据指定的格式进行解码,

另外get请求和post请求对编码格式的处理也是不同的


prepareStatement和statement的区别与联系:

PreparedStatement接口继承Statement,PreparedStatement实例包含已编译的SQL语句,所以执行速度要快于Statement对象,

Statement为一条SQL语句生成执行计划。

如果执行两条语句
select colume from table where colume = 1;
select colume from table where colume = 2;
会生成两个执行计划,一千个查询就生成一千个执行计划

preparedStatement用于绑定变量宠用执行计划 select colume from table where colume = :X
通过set不同数据只需要生成一次执行计划,可以重复适使用

Set、Queue、List都是继承了Collection这个接口,HashMap实现的接口有:Serializable,Cloneable,Map<K,V>

ConcurrentHashMap实际上是HashTable的升级版,使用segment来分段和管理锁的,并不是使用关键字

1.8之后使用 CAS+synchronized来保证线程安全


在Java中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问

default:(即是默认,什么也不写):在同一包内,不使用任何修饰类。使用对象:类、接口、变量、方法

private:在同一类内可见,使用对象:变量、方法。注意:不能修饰类(外部类)

public:对所有类可见,使用对象:类、接口、变量、方法

protected:对同一包内的类和所有子类可见。使用对象:变量、方法。注意不能修饰类(外部类)


重载和重写的关系:

首先,重载和重写都是多态的一种体现方式。重载是编译期间的活动,重写是允许期间的活动

其次,重载是一个类中定义相同名称的方法,方法的参数列表或者类型要互不相同,但是返回值类型不作为是否重载的标准,可以修改可见性

重写是不同的,要求子类重写基类的方法时要与父类方法具有相同的参数类型和返回值。可见性需要大于等于即类的方法

重写: 两小、一大、一同原则
子类重写父类方法,返回值为基本类型的时候,必须相同。
返回值为引用类型的时候,要小于等于父类
子类重写方法的修饰此要大于等于父类

两同:方法名和参数列表相同
两小:返回值或声明异常比父类小(或相同)   
一大:访问修饰符比父类的大(或相同)


instance是Java的二元运算符,用来判断它左边的对象是否为右面类(接口、抽象类、父类)的实例


TestSuper和Date的getClass都没有重写,他们都是调用Object的getClass,而Object的getClass作用是返回的是运行时的类的名字,这个运行是的类就睡当前类,【包名+类名】


java中的异常通常分为编译时异常和运行时候异常,

编译时异常需要我们手动的进行捕捉处理,也就是我们使用的try....catch块进行捕获处理。

运行时候的异常只有在编译器在编译运行时候才会出现,这些不需要我们手动处理

对于A,B,D来说都是运行时候的异常

1. 粉红色的是受检查的异常(checked exceptions),其必须被 try{}catch语句块所捕获,或者在方法签名里
通过throws子句声明.受检查的异常必须在编译时被捕捉处理,命名为 Checked Exception 是因为Java编译器
要进行检查,Java虚拟机也要进行检查,以确保这个规则得到遵守

2. 绿色的异常是运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 
空指针,被0除...
  
3. 而声明为Error的,则属于严重错误,如系统崩溃、虚拟机错误、

使用new关键词创建字符串对象时,JVM会先去检查 字符串常量池中 是否有存在的对应的字符串,

如果已经存在,则不会在字符串常量池中创建,

如果没有存在,那么就会 在字符串常量池中创建一个字符串对象,然后还会去 堆内存中创建一份字符串对象,

把常量池中的对象内容拷贝到 内存中的字符串对象,然后返回 堆内存中的字符串对象地址。


String对象的两种创建方法
	第一种:String str1 = "aaa"; 是在常量池中获取对象("aaa"属于字符串字面量,
因此编译时期会在常量池中创建一个字符串对象)
        
	第二种:String str2 = new String("aaa"),一共会创建两个字符串对象,一个是在堆中,一个是在常量
池中(前提是常量池中还没有:"aaa"字符串对象)
System.out.println(str1==str2); // false


doGet/doPost 则是在 javax.servlet.http.HttpServlet 中实现的


当我们在为Integer赋值的时候,java编译器会将其翻译成调用valueOf()方法。比如Integer i=127翻译为Integer i=Integer.valueOf(127),然后我们来看看valueOf()函数的源码:

public static Integer valueOf(int i)
{
    //high为127
    if(i >= -128&& i <= IntegerCache.high)
        return IntegerCache.***[i + 128];
    else
        return new Integer(i);
}

可以看出,对于-128到127之间的数,Java会对其进行缓存。而超出这个范围则新建一个对象。

所以现在回到这道问题

i1和i2为128,超出范围,所以都需要新建对象,对象比较为false;

i5和i6为100,在范围之内,在执行Integer i5=100时,就会直接缓存到内存中,

但执行执行Integer i6=100时,就直接从缓存里取,而不需要新建对象,所以为true。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值