- 浏览: 359005 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
fengxiatao:
忘了说我邮箱了 757723745@qq.com
关于 CAS SSO 文章声明 -
fengxiatao:
请发一下最github地址给我好吗?不胜感激
关于 CAS SSO 文章声明 -
romyli:
求一个github地址.感谢分享
关于 CAS SSO 文章声明 -
zz210891470:
使用您的例子从服务器获取lt返回test-login 页面之后 ...
CAS 之自定义登录页实践 -
feiteyizu:
WANTAWAY314 写道这种方法适合移动端的单点登录不?大 ...
CAS 之自定义登录页实践
因最近一直在学习 JVM,看到 BlueDavy 的一篇文章 JVM知识点题目,于是便激起了我去解答的兴趣。
字节码的加载
1、写一段将目录中指定的.class文件加载到JVM的程序,并通过Class对象获取到完整类名等信息;
对于 ClassLoader 的加载机制、过程及双亲委派模型等这里就不详细介绍了,基本上属于老生长谈的东西了。不过不了解朋友的可以看一下该作者文章:
深入JVM(4):关于ClassLoader的一些知识
先定义一个 DirectoryClassLoader继承 ClassLoader,通过加载指定的目录下的 class 文件,以下贴出该类的主要代码,完整的代码请从附件中下载。
OK, 接下为写个 Case 测试一把:
Class: Apple - ClassLoader: it.denger.jvm.classloader.DirectoryClassLoader@3d434234
Class: Banana - ClassLoader: it.denger.jvm.classloader.DirectoryClassLoader@3d434234
Class: it.denger.Pear - ClassLoader: it.denger.jvm.classloader.DirectoryClassLoader@3d434234
Class: java.lang.String - ClassLoader: null
目录结构:
可以看出,以上目录下的"所有" class 文件均已经加载,并且所对应的 ClassLoader 都为 DirectoryClassLoader。唯独 java.lang.String 类的 ClassLoader 为 null,其原因是由于 ClassLoader 的双亲委派模型,因为 String 属于 jre 核心库,已由 BootStrap ClassLoader 加载,而 BootStrap 的加载过程是由 C 实现,所以这里自然就是空了。
其实这题还有另外一个更加简单的方法,就是通过 URLClassLoader 进行加载,示例代码如下:
2、一段展示代码,里面包含一个全局静态整型变量,问如果用两个ClassLoader加载此对象,执行这个整型变量++操作后结果会是怎么样的?
继续使用上题的 ClassLoader 对象,修改 Apple.java为:
从 JVM加载 Class 的过程来说,对于同一包路径同名的 Class 是不会在同一ClassLoader进行重复加载的,当然,如果如这题所说,使用两个 ClassLoader 实例进行加载同一 Class ,这时候会产生两个 Class实例,原因是由于 ClassLoader 实例之间的相互隔离的。
以下测试用例是使用不同 ClassLoader 实例加载 Apple Class 之后并分别调用 addCount 一次:
~
方法的执行
1、A a=new A();a.execute();和 IA a=new A();a.execute();执行有什么不同;
简单的说,如果想知道方法的执行上有什么不同,那么先看一下它们的bytecode(字节码)有什么不同吧
Java 代码如下:
然而以上两个指令在到底在执行时有何不同,这得从 VM 的 Spec 说起了,你可以从以下几个链接中了解个大概:
Java字节码invokeinterface.... invokevirtual的含义和区别
invokeinterface, invokevirtual
What is the point of invokeinterface?
最后当然少不了 VM Spec 了,Sun VM Spec
2、反射的性能低的原因是?
关于这题,在 Sun 官方的 The Reflection API 明确说明了:
大致意思是说因为反射涉及到动态解析类型,以致于某些 jvm 不能够对其进行执行时的优化, 因此使用反射的性能低于非反射的性能..blabla...
上面所说的动态解析,意味着对于对象创建的过程、方法调用的过程是动态,通过动态加载字节码在 JVM 中进行执行,并且当使用 Class.forName 或 getMethod 时会执行权限校验检查以及lookup的过程,以至于这些调用操作必定将存在时间成本。
另外说的JVM不能进行优化,大致是说的是在对 Class 进行编译时候的优化(如在语义分析过程中会自动拆箱装箱处理),因为编译过程中是无法知道反射代码的真正所需要做的事情, 另外也可能无法发挥 JIT 的最大优化潜力。
值一提的是该问题是作者在09年发出,到目前为止,JDK反射提升越来越好了,从1.6版本后基本上与非反射方法调用相差无几了。当然,最好能在反射的代码进行缓存 Class 或 Method 对象,避免重复调用 getMethod 和 Class.forName,从而减少访问检查及lookup 的过程。
3、编写一段程序,动态的创建一个接口的实现,并加载到JVM中执行;(可以允许用BCEL等工具)
既然这里提到可以使用 BCEL 来实现接口的动态实现,那么就直接使用 BCEL 吧,顺便再复习一下 Builder 模式来进行代码的实现,将 Class 的创建与其具体的组成过程进行解耦。
首先定义一个 User 接口:
运行之后显示绿条,并在控制台输出了:
I'm jump....
I'm run....
OK, 至此已经完成本题的所有要求。虽然这里只是简单的实现两个无参、无返回值并且只是 println 输出,但是 BCEL 能做的远远不止这些,理论上来说只要你能手写出的代码基本上都能通过其 API 来动态生成字节码。P.S: 上面代码没写什么注释不过其代码看上去应该比较好懂,有什么可以提出.
~
如果对于以上我个人的分析和理解与你有什么偏差的话,希望能提出一起讨论,另外关于后面两大部分题,现在还在 writing 中,将在近期发出。
进入论坛讨论
字节码的加载
1、写一段将目录中指定的.class文件加载到JVM的程序,并通过Class对象获取到完整类名等信息;
对于 ClassLoader 的加载机制、过程及双亲委派模型等这里就不详细介绍了,基本上属于老生长谈的东西了。不过不了解朋友的可以看一下该作者文章:
深入JVM(4):关于ClassLoader的一些知识
先定义一个 DirectoryClassLoader继承 ClassLoader,通过加载指定的目录下的 class 文件,以下贴出该类的主要代码,完整的代码请从附件中下载。
package it.denger.jvm.classloader; package it.denger.jvm.classloader; public class DirectoryClassLoader extends ClassLoader { protected File directory; protected ClassLoader parent; public DirectoryClassLoader(File directory, ClassLoader parent) { // 将父 ClassLoader 传入super,用于classloader加载时向上查找 super(parent); ..... } public Class<?>[] findAndLoadAllClassInDirectory(){ // 获取当前目录中所有 class 文件的相对路径 String[] classPaths = getAllClassRelativePathInDirectory(directory); List<Class<?>> classes = new ArrayList<Class<?>>(classPaths.length); for (String classPath : classPaths){ try { // 将所有 class 文件相对路径转换为相应的包名 // 如 it/denger/Pear.class 则转换为 it.denger.Pear String className = convertPathToClassName(classPath); // 调用父类的 loadClass,该方法实现通过向上 一级级的ClassLoader // 进行查找,当所有上级全部无法找到时则会调用本ClassLoader的 // findClass 方法进行查找,也就是所谓的 “双亲委派模型” Class<?> classz = loadClass(className); if (classes != null){ classes.add(classz); } } catch (Exception e) { e.printStackTrace(); } } return classes.toArray(new Class<?>[0]); } // 重写父类 findClass,当所有 Parent Class Loader 无法找到类时, // 则会通过调用这里所该方法进行最后的查找 protected java.lang.Class<?> findClass(String name) throws ClassNotFoundException { Class<?> classz = null; // 通过 className 获取到对应的 File 对象 File classFile = new File(directory, convertClassNameToPath(name)); if (classFile.exists()) { try { // 重点在这里,从 class 的文件流中加载 Class 对象 classz = loadClassFromStream(name, new FileInputStream(classFile), (int)classFile.length()); } catch (Exception e) { throw new ClassNotFoundException(String.format("Find class %s error!", name), e); } } ..... return classz; } protected byte[] loadBytesFromStream(InputStream stream, int len) throws IOException{ byte[] streamBytes = new byte[len]; int read, off = 0; while(len > 0 && (read = stream.read(streamBytes, off, len)) != -1 ){ off += read; len -= read; } return streamBytes; } // 通过调用父类的 defineClass 将 字节 转为 Class 对象 protected Class<?> loadClassFromBytes(String name, byte []classBytes){ return defineClass(name, classBytes, 0, classBytes.length); } protected Class<?> loadClassFromStream(String name, InputStream stream, int len){ return loadClassFromBytes(name, loadBytesFromStream(stream, len)); } }
OK, 接下为写个 Case 测试一把:
public class DirectoryClassLoaderTest extends TestCase{ protected DirectoryClassLoader directoryClassLoader; protected String classDirectory; protected void setUp() throws Exception { classDirectory = "/Users/denger/Workspaces/Java/backup/classes"; directoryClassLoader = new DirectoryClassLoader(new File(classDirectory), this.getClass().getClassLoader()); } public void testShouldBeLoadedAllClassFileInDirectory(){ Class<?>[] classes = directoryClassLoader.findAndLoadAllClassInDirectory(); assertTrue(classes.length > 0); for(Class<?> classz : classes){ assertNotNull(classz); System.out.println("Class: " + classz.getName() + " - ClassLoader: " + classz.getClassLoader()); } }输入结果:
Class: Apple - ClassLoader: it.denger.jvm.classloader.DirectoryClassLoader@3d434234
Class: Banana - ClassLoader: it.denger.jvm.classloader.DirectoryClassLoader@3d434234
Class: it.denger.Pear - ClassLoader: it.denger.jvm.classloader.DirectoryClassLoader@3d434234
Class: java.lang.String - ClassLoader: null
目录结构:
可以看出,以上目录下的"所有" class 文件均已经加载,并且所对应的 ClassLoader 都为 DirectoryClassLoader。唯独 java.lang.String 类的 ClassLoader 为 null,其原因是由于 ClassLoader 的双亲委派模型,因为 String 属于 jre 核心库,已由 BootStrap ClassLoader 加载,而 BootStrap 的加载过程是由 C 实现,所以这里自然就是空了。
其实这题还有另外一个更加简单的方法,就是通过 URLClassLoader 进行加载,示例代码如下:
String classFileDirectory = "file:///Users/denger/Workspaces/Java/backup/classes/"; URLClassLoader classLoader = new URLClassLoader(new URL[]{new URL(classFileDirectory)}); System.out.println(classLoader.loadClass("it.denger.Pear"));不过我想以上这种通过URLClassLoader的实现这并不是作者所要考察的。
2、一段展示代码,里面包含一个全局静态整型变量,问如果用两个ClassLoader加载此对象,执行这个整型变量++操作后结果会是怎么样的?
继续使用上题的 ClassLoader 对象,修改 Apple.java为:
public class Apple{ public static int count = 1; public static void addCount(){ count++; } public static int getCount(){ return count; } }实际上,当两个ClassLoader加载此Class,并分别通过实例调用 addCount 时,其 count 是2还是3取决于分别加载的这两个 Apple Class 是否相等。
从 JVM加载 Class 的过程来说,对于同一包路径同名的 Class 是不会在同一ClassLoader进行重复加载的,当然,如果如这题所说,使用两个 ClassLoader 实例进行加载同一 Class ,这时候会产生两个 Class实例,原因是由于 ClassLoader 实例之间的相互隔离的。
以下测试用例是使用不同 ClassLoader 实例加载 Apple Class 之后并分别调用 addCount 一次:
public void testRepeatedLoadClass() { DirectoryClassLoader steveDirectoryClassLoader = new DirectoryClassLoader( new File(classDirectory), this.getClass().getClassLoader()); DirectoryClassLoader myDirectoryClassLoader = new DirectoryClassLoader( new File(classDirectory), this.getClass().getClassLoader()); Class<?> steveApple = steveDirectoryClassLoader.loadClass("Apple"); Class<?> myApple = myDirectoryClassLoader.loadClass("Apple"); // 产生不同的 Apple Class 实例,原因是以上两个 ClassLoader 实例是相互隔离的,他们都并知道对方加载了哪些 Class assertTrue(steveApple != myApple); // 分别调用 addCount steveApple.getMethod("addCount").invoke(null); myApple.getMethod("addCount").invoke(null); // 其 count 都为2,都只是 ++ 了自己的 count assertTrue(Integer.parseInt(steveApple.getMethod("getCount").invoke(null).toString()) == 2); assertTrue(Integer.parseInt(steveApple.getMethod("getCount").invoke(null).toString()) == Integer.parseInt(myApple.getMethod("getCount").invoke(null).toString())); }
~
方法的执行
1、A a=new A();a.execute();和 IA a=new A();a.execute();执行有什么不同;
简单的说,如果想知道方法的执行上有什么不同,那么先看一下它们的bytecode(字节码)有什么不同吧
Java 代码如下:
package it.denger.jvm.code; public class MethodExecute { public static void main(String[] args) { A a = new A(); a.execute(); IA ia = new A(); ia.execute(); } } interface IA{ public void execute(); } class A implements IA{ public void execute() { System.out.println("A execute call...."); } }通过 javap -c it.denger.jvm.code.MethodExecute 命令查看代码的字节码信息,其中 main 方法的字节码如下:
public static void main(java.lang.String[]); Code: 0: new #2; //class it/denger/jvm/code/A 3: dup 4: invokespecial #3; //Method it/denger/jvm/code/A."<init>":()V 7: astore_1 8: aload_1 9: invokevirtual #4; //Method it/denger/jvm/code/A.execute:()V 12: new #2; //class it/denger/jvm/code/A 15: dup 16: invokespecial #3; //Method it/denger/jvm/code/A."<init>":()V 19: astore_2 20: aload_2 21: invokeinterface #5, 1; //InterfaceMethod it/denger/jvm/code/IA.execute:()V 26: return }对 exeucte 方法的调用主要在第 9 行和第 21行,不难看出,他们的调用所使用的指令不一样,分别为 invokevirtual(调用对象方法) 和 invokeinterface(调用接口中方法)。
然而以上两个指令在到底在执行时有何不同,这得从 VM 的 Spec 说起了,你可以从以下几个链接中了解个大概:
Java字节码invokeinterface.... invokevirtual的含义和区别
invokeinterface, invokevirtual
What is the point of invokeinterface?
最后当然少不了 VM Spec 了,Sun VM Spec
2、反射的性能低的原因是?
关于这题,在 Sun 官方的 The Reflection API 明确说明了:
引用
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
大致意思是说因为反射涉及到动态解析类型,以致于某些 jvm 不能够对其进行执行时的优化, 因此使用反射的性能低于非反射的性能..blabla...
上面所说的动态解析,意味着对于对象创建的过程、方法调用的过程是动态,通过动态加载字节码在 JVM 中进行执行,并且当使用 Class.forName 或 getMethod 时会执行权限校验检查以及lookup的过程,以至于这些调用操作必定将存在时间成本。
另外说的JVM不能进行优化,大致是说的是在对 Class 进行编译时候的优化(如在语义分析过程中会自动拆箱装箱处理),因为编译过程中是无法知道反射代码的真正所需要做的事情, 另外也可能无法发挥 JIT 的最大优化潜力。
值一提的是该问题是作者在09年发出,到目前为止,JDK反射提升越来越好了,从1.6版本后基本上与非反射方法调用相差无几了。当然,最好能在反射的代码进行缓存 Class 或 Method 对象,避免重复调用 getMethod 和 Class.forName,从而减少访问检查及lookup 的过程。
3、编写一段程序,动态的创建一个接口的实现,并加载到JVM中执行;(可以允许用BCEL等工具)
既然这里提到可以使用 BCEL 来实现接口的动态实现,那么就直接使用 BCEL 吧,顺便再复习一下 Builder 模式来进行代码的实现,将 Class 的创建与其具体的组成过程进行解耦。
首先定义一个 User 接口:
package it.denger.jvm.code.bcel; public interface IUser { void jump(); void run(); }然后针对该接口动态类生成定义一个 Builder 接口:
package it.denger.jvm.code.bcel; import org.apache.bcel.generic.ClassGen; public interface UserClassGenBuilder { static final String USER_CLASS_NAME = "it.denger.jvm.code.bcel.IUser"; UserClassGenBuilder init(String className); UserClassGenBuilder implementJumpMethod(); UserClassGenBuilder implementRunMethod(); ClassGen build(); }对于 User 接口来说,具体实现可能有 Student、Staff等,以下以 Student 为例,定义 StudentClassGenBuilder,动态生成 Student User 及实现 jump 和 run 方法:
public class StudentClassGenBuilder implements UserClassGenBuilder{ protected String className; protected ClassGen classGen; public StudentClassGenBuilder init(String className) { this.className = className; classGen = new ClassGen(className, "java.lang.Object", "<generated>", ACC_PUBLIC | ACC_SUPER, new String[] { USER_CLASS_NAME }); classGen.addEmptyConstructor(ACC_PUBLIC); return this; } public UserClassGenBuilder implementJumpMethod() { InstructionFactory instructionFactory = new InstructionFactory(classGen); InstructionList instructionList = new InstructionList(); ConstantPoolGen constantPool = classGen.getConstantPool(); MethodGen methodGen = new MethodGen(ACC_PUBLIC, Type.VOID, new Type[0], new String[0], "jump", className, instructionList, constantPool); instructionList.append(instructionFactory.createPrintln("I'm jump....")); instructionList.append(InstructionFactory.createReturn(Type.VOID)); methodGen.setMaxStack(); classGen.addMethod(methodGen.getMethod()); return this; } public UserClassGenBuilder implementRunMethod() { InstructionFactory instructionFactory = new InstructionFactory(classGen); InstructionList instructionList = new InstructionList(); ConstantPoolGen constantPool = classGen.getConstantPool(); MethodGen methodGen = new MethodGen(ACC_PUBLIC, Type.VOID, new Type[0], new String[0], "run", className, instructionList, constantPool); instructionList.append(instructionFactory.createPrintln("I'm run....")); instructionList.append(InstructionFactory.createReturn(Type.VOID)); methodGen.setMaxStack(); classGen.addMethod(methodGen.getMethod()); return this; } public ClassGen build() { return classGen; }可以看出以上已经完成了两个方法的实现,并返回 ClassGen 对象(用于生成具体 Class 的对象)。但该题最终是需要将动态的实现的 Class 加载至 JVM中,并调用动态实现的方法,于是以下的 UserClassGenLoader 便产生了:
public class UserClassGenLoader { protected UserClassGenBuilder builder; public UserClassGenLoader(UserClassGenBuilder builder){ this.builder = builder; } public Class<?> loadClass(String className) throws ClassNotFoundException, IOException{ ClassGen classGen = this.builder.init(className) .implementJumpMethod().implementRunMethod().build(); return loadClassForClassGen(classGen); } protected Class<?> loadClassForClassGen(ClassGen classGen) throws ClassNotFoundException, IOException{ ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); classGen.getJavaClass().dump(arrayOutputStream); byte[] classBytes = arrayOutputStream.toByteArray(); Map<String, byte[]> classByteMap = new HashMap<String, byte[]>(); classByteMap.put(classGen.getClassName(), classBytes); ByteClassLoader byteClassLoader = new ByteClassLoader(this.getClass() .getClassLoader(), classByteMap); return byteClassLoader.loadClass(classGen.getClassName()); } }至此已经完成从动态接口实现至将其加载至 JVM 中,并获取最终的 Class 对象,最后写一个 TestCase 测试一把:
public void testShouldBeLoadStudentNewInstance() { try { Class<?> studentClass = new UserClassGenLoader(new StudentClassGenBuilder()) .loadClass("it.denger.jvm.code.bcel.Student"); IUser studentUser = (IUser) studentClass.newInstance(); assertNotNull(studentUser); assertEquals(studentUser.getClass().getName(), "it.denger.jvm.code.bcel.Student"); studentUser.jump(); studentUser.run(); } catch (Exception e) { fail(e.getMessage()); } } }
运行之后显示绿条,并在控制台输出了:
I'm jump....
I'm run....
OK, 至此已经完成本题的所有要求。虽然这里只是简单的实现两个无参、无返回值并且只是 println 输出,但是 BCEL 能做的远远不止这些,理论上来说只要你能手写出的代码基本上都能通过其 API 来动态生成字节码。P.S: 上面代码没写什么注释不过其代码看上去应该比较好懂,有什么可以提出.
~
如果对于以上我个人的分析和理解与你有什么偏差的话,希望能提出一起讨论,另外关于后面两大部分题,现在还在 writing 中,将在近期发出。
进入论坛讨论
发表评论
-
关于 CAS SSO 文章声明
2015-03-21 14:39 3114由于几年前写了几篇 CAS 系列的文章,之后陆续有人参照文章去 ... -
JVM知识点题目解答之二
2012-01-17 21:13 0本文将继续解答JVM知识点题目后面两大题目,前面的两大部分已经 ... -
JVM知识点题目解答
2011-12-29 01:03 1因最近一直在学习 JVM,看到 BlueDavy 的一篇文章 ... -
记录帖:碰到的一些Java问题
2011-11-15 22:44 3288Move to: https://denger.github. ... -
MyBatis 缓存机制深度解剖 / 自定义二级缓存
2011-07-17 19:52 41297缓存概述 正如大多数 ... -
MyBatis+Spring基于接口编程的原理分析
2011-05-27 02:43 17520move to: http://www.iteye.com/t ... -
新浪微博如何实现 SSO 的分析
2011-05-10 14:44 24725最近在使用sina微博时,经常性交替使用 weibo ... -
基于Nginx XSendfile+SpringMVC进行文件下载
2011-04-24 12:29 5115在平常我们实现文 ... -
Java IO 与 NIO 探讨
2011-03-29 16:30 0aaaaaaaaaaaaaaaaaa -
自定义 Java Annotation及应用
2010-11-08 15:04 9543作为一个Javaer 我想对于 Java Annot ...
相关推荐
本文将全面探讨这些核心知识点,并提供相关面试题目的解答。 首先,JVM内存主要分为五个区域:堆区、栈区、方法区、本地方法栈和程序计数器。堆区是所有对象的诞生地,包括数组,分为新生代(Eden + Survivor,...
【标题】"JVM面试题 PDD 下载"所涉及的知识点主要集中在Java虚拟机(JVM)上,这是Java编程中的核心部分,对于开发者尤其是面试者来说,深入理解JVM至关重要。PDD可能指的是“问题、解答、讨论”或者“拼多多”(PDD...
标题 "JAVA题目&答案" 暗示了这是一个与Java编程相关的学习资源,可能包含了各种Java编程题目及其解答。从描述中的“博文链接”可以看出,它可能来源于一位名为“zhuenwei”的博主在iteye博客平台上发布的内容。标签...
以下是一些关键知识点的详细解释: 1. **网络系统**: - **三次握手与四次挥手**:这是TCP/IP连接建立和关闭的过程。三次握手确保了双方都有能力发送和接收数据,防止已失效的连接请求报文突然重新出现导致错误。...
这两份xls文件可能包含了上述知识点的具体题目和解答,通过解答这些题目,学员不仅可以巩固已学知识,还能发现自己的知识盲区,进一步提升编程技能。建议在学习过程中结合实际项目练习,以加深理解并提高问题解决...
根据给定的信息,以下是从这份文档中提取的关键知识点及其详细解释: ### 1. 内存回收机制 **题目:** 下列哪些语句关于内存回收的说明是正确的? (b) - **选项 A:** 程序员必须创建一个线程来释放内存 - **选项 B:*...
在解压后的“蚂蚁金服上机题目和答案”文件中,可能会包含模拟蚂蚁金服实际面试中遇到的编程题,这些问题可能涉及上述提到的多个Java知识点。通过这些题目,求职者可以了解蚂蚁金服对技术能力的具体要求,并针对性地...
Java笔试题知识点及答案涵盖了Java语言的基础到进阶的各个层面,是准备Java程序员面试或笔试的重要参考资料。...在实际的"java笔试题大集合及答案"文件中,你可以找到具体的题目和解答,帮助巩固理解和应用这些知识点。
"java三份题目附录答案"可能是指一个包含了三套Java编程试题及其解答的资源,对于学习者来说,这是一个很好的实践和自我测试的工具。下面我们将深入探讨Java编程的一些关键知识点,这些知识点可能会在试题中出现。 ...
以下是根据这些题目和答案整理出的一些关键知识点: 1. **Java基础语法**:Java的基础语法包括变量声明、数据类型(如int、double、String等)、运算符(算术、比较、逻辑等)、控制流(if-else、switch、for、...
综合以上信息,我们可以预想这份"Java面试题目2"可能会涵盖以下知识点: 1. **基础语法**:包括变量、数据类型、运算符、流程控制语句等。 2. **面向对象**:封装、继承、多态,以及接口和抽象类的区别。 3. **集合...
Java 面试全解析:核心知识点与典型面试题 面试是评估个人技能和技术知识的重要方式,特别是在IT行业中,尤其是Java开发岗位。为了在激烈的竞争中脱颖而出,掌握扎实的Java核心技术,了解高频面试题,以及背后的...
【标题】"四百道JAVA和ORACLE笔试面试题目...对于每一个文件,如"java经典题目.doc"、"Java题目汇总.doc"、"1oracle类.doc"、"java基础.txt",都应认真研读,理解并尝试解答,以确保对这些知识点有深入的理解和掌握。
【C#知识点】 C#是一种由微软开发的面向对象的编程语言,广泛应用于Windows平台的应用程序开发和游戏制作。在C#面试中,可能会遇到以下知识点: 1. 类与对象:理解面向对象的基本概念,如封装、继承和多态。 2. ...
根据提供的文档内容,我们可以总结出以下几个关键知识点: ### 1. 表达式的逻辑运算 - **题目描述**:如果 `x=2`,则表达式 `x+1>2 Or sin(x)>0.9 And 3>x+3` 的值是什么? - **解答**:在这个表达式中,首先计算 ...
从提供的文件内容来看,这是一份针对2017年完美世界校园招聘的技术综合试卷A卷,试卷中涉及了计算机科学的多个知识点,包括编程基础、操作系统、网络协议、数据结构、算法原理、内存模型以及多线程编程。下面将详细...
10. **Java面试题**:本资源中的自测题目涵盖了上述知识点,同时也可能包含一些Java面试常见问题,如JVM调优、并发编程、数据结构与算法等,为面试做足准备。 这套自测题目旨在全面检验和提升Java学习者的综合能力...
以下是对这些面试题目的深入解析和相关知识点的详细阐述。 C++作为一门静态类型、编译式、通用的面向对象编程语言,其面试题目常常围绕以下几个核心概念: 1. **面向对象编程(OOP)**:C++的面试题目经常考察封装...
Java认证考试通常指的是Oracle Certified ...提供的"010101-李明-选择题答案示例.xlsx"可能是选择题的解答参考,而"testfiles"可能包含其他类型的题目或样例代码。利用这些资源,考生可以更好地为考试做准备。