提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
记录一次Java面试经历
一、ROM与RAM的区别。
- 存储器是数字系统中用以存储大量信息的设备或部件,是计算机和数字设备中的重要组成部分。存储器可分为随机存取存储区(RAM)和只读存储器(ROM)两大类。要说他俩有什么区别,请接着往下看。
- RAM和ROM都是一种存储技术,只是两者原理不同,RAM为随机存储,掉电不会保存数据,而ROM可以在掉电的情况下,依然保存原有数据。ROM是Read-Only
Memory的意思,也就是说这种存储器只能读,不能写。而RAM是Ram Access Memory的缩写。RAM可以随机读写。 - RAM(Random Access Memory)易挥发性随机存储器,高速存取,读写时间不相等,且与地址无关,如计算机内存等。
- ROM(Read Only Memory)只读存储器。断电后信息不丢失,如计算机启动调用的BIOS芯片。存取速度很低,(较RAM而言)且不能改写。由于不能改写信息,不能升级,现在已经很少使用。
- ROM和RAM是计算机内存储器的两种型号,ROM表示只读存储器,即:他只能读出信息,不能写入信息,计算机关闭电源后其内的信息仍旧保存,一般用它存储固定的系统软件和字库等。
- RAM表示的是读写存储器,可对其中的任一存储单元进行读或者写的操作,计算机关闭电源后,其内部的信息将不再保存,再次开机时需要重新装入,通常用来存放操作系统,各种正在运行的软件、输入和输出数据,中间结果及与外存储交换信息等,我们常说的内存主要是指RAM。
二、值传递与应用传递的区别。
这个问题比较基础,下面提供两个连接,有需要的可以看一下。
https://blog.csdn.net/Start1234567/article/details/109373902
https://segmentfault.com/a/1190000016773324
三、什么是反射机制?
1、Class.forName(“全类名”)
将字节码文件加载进内存,返回Class对象
多用于配置文件,将类名定义在配置文件中。读取文件,加载类。
推荐使用这种方式。
//1.class.forName("全类名")
Class class1 = Class.forName("com.zzy.feflect.Student");
System.out.println(class1);
2、类名.class
通过类名的属性class获取
多用于参数的传递
//2.类名.class
Class class2 = Student.class;
System.out.println(class2);
3、对象.getClass()
getClass()方法再Object类中定义着。
多用于对象获取字节码文件的方式。
//3.对象.getClass()
Class class3 = new Student().getClass();
System.out.println(class3);
public class Test{
public static void main(String[] args) throws Exception{
//1.class.forName("全类名")
Class class1 = Class.forName("com.zzy.feflect.Student");
System.out.println(class1);
//2.类名.class
Class class2 = Student.class;
System.out.println(class2);
//3.对象.getClass()
Class class3 = new Student().getClass();
System.out.println(class3);
System.out.println(class1 == class2);
System.out.println(class1 == class3);
}
}
如果不需要动态的创建一个对象,就不需要使用反射。
单设调用方法时,可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
1、java反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或者对象的属性和方法。本质是JVM得到class对象之后,再通过class对象进行反编译,从而获取对象的各种信息。
2、java属于先编译再运行的语言,城西中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象,并调用其属性和方法,而不需要在编译期知道运行的对象是谁。
反射的优缺点
1、优点:在运行时获得类的各种内容,进行反编译,对于java这种先编译在运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。
2、缺点:
反射会消耗一定的系统资源,因此,如果不要需要动态地创建一个对象,那么就不需要动态的创建一个对象,那么就不需要用反射。
反射调用方法时看可以忽略权限检查,因此可能会破坏封装性而导致安全问题。
反射的用途:
1、反编译:.class—>.java
2、通过反射机制访问java对象的属性,方法,构造方法等。
3、当我们在使用IDE,比如ecplise时,当我们输入一个对象或者类,并想调用它的属性和方法时,可以通过.属性的方式访问该对象/类的属性和方法,这就是用到反射。
4、反射最重要的用途就是开发各种通用的框架。(Spring)都是配置化的(比如通过XML文件配置Bean),为了保证框架的通用性,它们可能需要根据配置文件加载不同的类或者对象。
5、例如,在使用Struct2框架中的开发过程中,我们一般会在structs.xml里去配置Action,比如
比如我们请求login.action时,那么StructPrepareAndExecuteFilter就会去解析structs.xml文件,从action中查找name为login的Action,并根据class属性创建SimpleLoginAction实列,并用Invoke方法来调用execute方法,这个过程离不开反射。配置文件与Action建立一种映射关系,当View层发出请求时,请求会被StructsPrepareAndExecuteFilter拦截,然后StructPrepareAndExecuteFilter会去动态地创建Action实列。
比如,加载数据库驱动时,也是用到的反射机制。
Class.forName(“com.mysql.jdbc.Driver”);//动态加载mysql驱动
获得Class的三种方法:
1、对象.getClass
Student stu1 = new Student();//这一new 产生一个Student对象,一个class对象。
Class stuClass = stu1.getClass();//获取class对象
System.out.println(stuClass.getName());
2、任何数据类型(包括基本数据类型)都有一个“静态”的class属性
Class stuClass2 = Student.class;
System.out.println(stuClass2.getName());
3、通过class类的静态方法:forName(String className)
try{
Class stuClass3 = Class.forName(“fanshe.Student”);//注意此处的字符串必须是填真实路径,就是带包名的类路径,包名.类名
System.out.println(stuClass3.getName());
}catch(ClassNotFoundException e){
e.printStackTrace();
}
注意,在运行期间,一个类,只有一个Class对象产生,所有的Class对象都是同一个对象。
三种方式中,常用的是第三种,第一种对象都有了,还要反射干什么,第二种需要导入类包,依赖太强,不导包就跑编译错误。一般都使用第三种方式,一个字符串可以传入,也可以写在配置文件中等多种方法。
四、列举String的常用方法。
- indexOf(“字符”):查询指定字符串是否存在,返回的是字符串的位置,不存在则返回-1;
String str = "武汉加油";
int str1 = str.indexOf("加");//查找“加”的位置
int str2 = str.indexOf(str:"加",fromIndex:1);//查找“加”的位置,从第二个开始查找
- CharAt(值):拿到指定位置的字符;
String str = "端午节快乐";
char str str1 = str.charAt(2);//取出位置在2的字符串,结果为“加”
- trim():去除字符串两端的空格;
String str = " 端午节快乐 ";
String str1 = str.trim();//去掉前后空格,结果为“端午节快乐”
- split():分割字符串,返回分割后的字符串数组;
String str = "端,午,节,快,乐";
String[] str1 = str.split(str);//根据“,”分割
//str1{"端","午","节","快","乐"}
- length():返回字符串的长度;
String str = "SpringMVC";
int str1 = str.length();//结果为9
- substring(int beginIndex,int endIndex):截取字符串;
String str = "端午节快乐";
//截取1-3的字符,不包含3
String str1 = str.substring(1,3);//结果为"午节"
//从第二个位置截取,包含2
String str2 = str.substring(1);//结果为"午节快"
- equals():比较两个字符串是否相等;
String str = "武汉加油";
String str1 = "端午快乐";
//如果两个值相同,flag=true,否则为false
boolean flag = str.equals(str1);//此处flag = false
- toLowerCase():将字符串转为小写字母;
String str = "SpRIngMvc";
//把大写字母转换为小写字母
String str1 = str.toLowerCase();//结果为"springmvc"
- toUpperCase():将字符串转换为大写字母;
String str = "SpringMVc";
//把小写字母转为大写字母,
String str1 = str.toUpperCase();//结果为"SPRINGMVC"
- equalsIgnoreCase(String):忽略大小写比较两个值是否相等
String str = "SpRINGmvc";
String str2 = "springMVc";
if(str.equaslIgnoreCase(str1)){
System.out.println("相等");
}else{
System.out.println("不相等");
}
//返回的是布尔值,结果为"相等"。
- replace():替换字符串,把第一次出现的位置替换掉;
String str = "端午端午节快了";
String str1 = "端午节快乐";
String str2 = str.replace(target:"端午",replacement:"大家");//str2 "大家端午节快乐"
String str3 = str1.replace(target:"端午",replacement:"中秋");//str3 "中秋节快乐"
五、get和post的区别?
1.基础版
- 在面试的过程中,总会被面试官问道:“请你回答一下GET请求和POST请求的区别?”
大家的回答一般都是如下图:
2.进阶版
1.报文上的区别
- GET 和 POST 只是 HTTP 协议中两种请求方式,所以在传输上,没有区别,因为HTTP 协议是基于 TCP/IP 的应用层协议
- 报文格式上,不带参数时,最大区别仅仅是第一行方法名不同,一个是GET,一个是POST
- 带参数时报文的区别呢?在约定中,GET 方法的参数应该放在 url 中,POST 方法参数应该放在 body 中
举个例子,如果参数是 name=zhiying.c, age=22。
-
GET 方法简约版报文可能是这样的
GET /index.php?name=zhiying.c&age=22 HTTP/1.1 Host: localhost -
POST 方法简约版报文可能是这样的
POST /index.php HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded name=zhiying. c&age=22
2.GET 方法参数写法是固定的吗?
- 在约定中,一般我们的参数是写在 ? 后面,用 & 分割。 我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取
Header 和 Body,从而提取参数。 也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行,一种比较流行的写法是这样 :
http://www.example.com/user/name/yourname/age/22
3、POST 方法比 GET 方法安全?
- 按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。 然而从传输的角度来说,他们都是不安全的,因为 HTTP
在网络上是明文传输,只要在网络节点上抓包,就能完整地获取数据报文。 要想安全传输,就只有加密,也就是 HTTPS
六、分别解释session和cookie。
session是在服务器端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中
cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Seeion的一种方式。
session是一个抽象概念,开发者为了实现中断和继续等操作,将user agent和server之间一对一的交互,抽象为“会话”。这也就是session的概念。
cookie是一个实际存在的东西,是http协议中定义在header中的字段。可以认为session的一种后端无状态实现。
而我们今天常说的“session”,是为了绕开cookie的各种限制,通常借助cookie本身和后端存储实现的,一种更高级的会话状态实现。
所以cookie和session,你可以认为是同一层次的概念,也可以认为是不同层次的概念。具体到实现,session因为session id的存在,通常要借助cookie实现,而这并非必要,只能说是通用性较好的一种实现。
1、session在服务器端,cookie在客户端(浏览器)。
2、session默认被存在服务器的一个文件里。
3、session的运行依赖session id,而session id是存在cookie中的,也就是说,如果浏览器禁用cookie之后,同时session也会失效(但是可以通过去哦他方式实现,比如在url中传递session_id)
4、session可以存放在文件、数据库、或者内存中都可以。
5、用户验证这种场合一般会用session
因此,维护一个会话的核心就是客户端的唯一标识,即session id
七、简述MVC架构模式。
- MVC 模型(Model):后端,包含了所有数据逻辑
模型的任务是夫案例数据。不论数据来自数据库、API还是JSON对象,模型都要负责管理他们。 在Car
Cliker应用中,模型对象包含一个由car对象组成的数组,其中含有这个应用所需的所有信心(数据)。
它还通过一个初始值为null的变量currentCar控制当前展示哪个汽车。 - 视图(View):前端界面或者GUI 视图决定了用户看到的内容以及交互方式。 Car
Cliker应用有两个视图:carListView和CarView 每个视图都有两个关键的函数,定义其如何初始化及如何渲染。
这些函数决定了用户将会看到的内容以及交互方式。 - 控制器(Controller):应用的大脑,控制数据如何展示。
控制器负责获取数据、修改数据,并为用户提供数据。本质上,控制器就是视图和模型之间的链接。
通过getter和setter函数,控制器从模型拉取数据并初始化视图。 如果试图要更新后台数据,它会通过setter函数来修改数据。
- 模型(Model):负责存储系统的中心数据。 视图(View):将信息显示给用户(可以定义多个视图)。
控制器(Controller):处理用户输入的信息。负责从视图读取数据,控制用户输入,并向模型发送数据,是应用程序中小狐狸用户交互的部分。负责管理用户交互控制。 - 视图和控制器共同构成了用户接口。
每个视图都有一个相关的控制器组件。控制器接受输入,通常作为鼠标移动、鼠标按钮活动或者键盘输入编码的事件。时间被翻译成模型或视图的服务器请求,用户仅仅通过控制器与系统交互。 - 特点 MVC重要的特点就是两种分离:
视图和数据模型的分离;使用了不同的视图对相同的数据进行展示;分离可视和不可视的组件,能够对模型进行独立测试。因为分离了可视组件,减少了外部依赖,有利于测试。(数据库也是一种外部组件)。
视图和表现逻辑(Controller)的分离;Controller使一个表现逻辑的组件,并非一个业务逻辑组件。MVC可以作为表现模式也可以作为构建模式,这意味着Controller也可以是业务逻辑。发呢里逻辑和具体展示,能都对逻辑进行独立测试。 - 优点:耦合性低;重用性高;生命周期成本低;部署快;可维护性高;有利于软件工程模块化管理。
- 缺点:没有明确的定义;不适合小型、中等规模的应用程序;增加系统结构和实现的复用性;视图与控制器间的连接过于紧密;视图对模型数据的低效访问;一般高级的界面工具或者构造器不支持模式。
八、总结
以上就是本次面试的我认为比较有价值的知识点,当然这是只针对刚毕业半年左右的初级程序员。如果你觉得本次分享还不错的话,不妨点赞、投币、一键三连。