java基础细节

String str="aaa"与 String str=new String(“aaa”)一样吗? new String(“aaa”); 创建了几个字符串对象?

  • 使用String a = “aaa” ,程序运行时会在常量池中查找”aaa”字符串,若没有,会将”aaa”字符串放进常量池,再将其地址赋给a;若有,将找到的”aaa”字符串的地址赋给a。

  • 使用String b = new String("aaa"),程序会在堆内存中开辟一片新空间存放新对象,同时会
    将”aaa”字符串放入常量池,相当于创建了两个对象,无论常量池中有没有”aaa”字符串,程序都会 在堆内存中开辟一片新空间存放新对象。

Integer变量和int变量的对比

Integer变量和int变量比较时,只要两个变量的值是向等的,则结果为true(因为包装类Integer和基本 数据类型int比较时,java会自动拆包装为int,然后进行比较,实际上就变为两个int变量的比较)

int a = 10000;
Integer b = new Integer(10000); 
Integer c=10000; System.out.println(a == b); 
// true 
System.out.println(a == c);
 // true

在这里插入图片描述
2.
在这里插入图片描述
3.
在这里插入图片描述

如何获取反射中的Class对象?

Class.forName(“类的路径”);当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。

	Class clz = Class.forName("java.lang.String");

类名.class。这种方法只适合在编译前就知道操作的 Class。

	Class clz = String.class;

对象名.getClass()。 

	String str = new String("Hello"); 
	Class clz = str.getClass();

如果是基本类型的包装类,可以调用包装类的Type属性来获得该包装类的Class对象。

使用反射获取一个对象的步骤:

获取类的 Class 对象实例

Class clz = Class.forName("com.zhenai.api.Apple");

根据 Class 对象实例获取 Constructor 对象

Constructor appleConstructor = clz.getConstructor();

使用 Constructor 对象的 newInstance 方法获取反射类对象

 Object appleObj = appleConstructor.newInstance();

而如果要调用某一个方法,则需要经过下面的步骤: 获取方法的 Method 对象

 Method setPriceMethod = clz.getMethod("setPrice", int.class);

利用 invoke 方法调用方法

setPriceMethod.invoke(appleObj, 14);

第一种:JDBC 的数据库的连接

在JDBC 的操作中,如果要想进行数据库的连接,则必须按照以上的几步完成

  • 通过Class.forName()加载数据库的驱动程序 (通过反射加载,前提是引入相关了Jar包);
  • 通过 DriverManager 类进行数据库的连接,连接的时候要输入数据库的连接地址、用户名、密码;
  • 通过Connection 接口接收连接。
public class ConnectionJDBC {

/**
* @param args
*/
//驱动程序就是之前在classpath中配置的JDBC的驱动程序的JAR 包中
public static final String DBDRIVER = "com.mysql.jdbc.Driver";
//连接地址是由各个数据库生产商单独提供的,所以需要单独记住
public static final String DBURL = "jdbc:mysql://localhost:3306/test";
//连接数据库的用户名
public static final String DBUSER = "root";
//连接数据库的密码
public static void main(String[] args) throws Exception { Connection con = null; //表示数据库的连接对象
Class.forName(DBDRIVER); //1、使用CLASS 类加载驱动程序 ,反射机制的体现
con = DriverManager.getConnection(DBURL,DBUSER,DBPASS); //2、连接数据库System.out.println(con);
con.close(); // 3、关闭数据库
}

第二种:Spring 框架的使用,最经典的就是xml的配置模式。

  • Spring 通过 XML 配置模式装载 Bean 的过程:
  • 将程序内所有 XML 或 Properties 配置文件加载入内存中;
  • Java类里面解析xml或properties里的内容,得到对应实体类的字节码字符串以及相关的属性信息;
  • 动态配置实例的属性。

反射机制的原理是什么?

Class actionClass=Class.forName(MyClass); 
Object action=actionClass.newInstance();
Method method = actionClass.getMethod(“myMethod”,null); 
method.invoke(action,null);

上面就是最常见的反射使用的例子,前两行实现了类的装载、链接和初始化(newInstance方法实际上也是使用反射调用了方法),后两行实现了从class对象中获取到method对象然后执行反射调用。

泛型是一种语法糖,泛型这种语法糖的基本原理是类型擦除。

Java中的泛型基本上都是在编译器这个层次来实现的,也就是说:泛型只存在于编译阶段,而不存在于运行阶段。在编译后的 class 文件中, 是没有泛型这个概念的
类型擦除:使用泛型的时候加上的类型参数,编译器在编译的时候去掉类型参数

什么是serialVersionUID?

serialVersionUID 用来表明类的不同版本间的兼容性

Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化
时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较, 如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。

Java 序列化中如果有些字段不想进行序列化,怎么办?

对于不想进行序列化的变量,使用 transient 关键字修饰。

transient 关键字的作用是控制变量的序列化,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后, transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
transient 只能修饰变量,不能修饰类和方法。

synchronized和ReentrantLock 的区别

  1. 两者都是可重入锁
    可重入锁:重入锁,也叫做递归锁,可重入锁指的是在一个线程中可以多次获取同一把锁,比如:
    一个线程在执行一个带锁的方法,该方法中又调用了另一个需要相同锁的方法,则该线程可以直接执行 调用的方法,而无需重新获得锁,两者都是同一个线程每进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。

  2. synchronized 依赖于 JVM 而 ReentrantLock 依赖于 API
    synchronized 是依赖于 JVM 实现的,前面我们也讲到了 虚拟机团队在 JDK1.6 为 synchronized 关键字进行了很多优化,但是这些优化都是在虚拟机层面实现的
    ReentrantLock 是 JDK 层面实现的(也就是 API 层面,需要 lock() 和 unlock() 方法配合 try/finally
    语句块来完成)

  3. ReentrantLock 比 synchronized 增加了一些高级功能
    相比synchronized,ReentrantLock增加了一些高级功能。主要来说主要有三点:①等待可中断;②可实现公平锁;③可实现选择性通知(锁可以绑定多个条件)

  • 等待可中断.通过lock.lockInterruptibly()来实现这个机制。也就是说正在等待的线程可以选择放弃等待,改为处理其他事情。
  • ReentrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁 就是先等待的线程先获得锁。 ReentrantLock默认情况是非公平的,可以通过 ReentrantLock类的ReentrantLock(boolean fair)构造方法来制定是否是公平的。
  • ReentrantLock类线程对象可以注册在指定的Condition中,从而可以有选择性的进行线程通知,在调度线程上更加灵活。 在使用notify()/notifyAll()方法进行通知时,被通知的线程是由 JVM 选择的,用ReentrantLock类结合Condition实例可以实现“选择性通知”
    4. 使用选择
    除非需要使用 ReentrantLock 的高级功能,否则优先使用 synchronized。
    synchronized 是 JVM 实现的一种锁机制,JVM 原生地支持它,而 ReentrantLock 不是所有的 JDK版本都支持。并且使用 synchronized 不用担心没有释放锁而导致死锁问题,因为 JVM 会确保锁的释放

Thread类中的yield方法有什么作用?

Yield方法可以暂停当前正在执行的线程对象,让其它有相同优先级的线程执行。它是一个静态方法
而且只保证当前线程放弃CPU占用而不能保证使其它线程一定能占用CPU,执行yield()的线程有可能在 进入到暂停状态后马上又被执行。

谈谈volatile的使用及其原理?

volatile的两层语义:
1、volatile保证变量对所有线程的可见性:当volatile变量被修改,新值对所有线程会立即更新。或者理 解为多线程环境下使用volatile修饰的变量的值一定是最新的。
2、jdk1.5以后volatile完全避免了指令重排优化,实现了有序性。

volatile的原理:

获取JIT(即时Java编译器,把字节码解释为机器语言发送给处理器)的汇编代码,发现volatile多加了lock addl指令,这个操作相当于一个内存屏障,使得lock指令后的指令不能重排序到内存屏障前的位置。这也是为什么JDK1.5以后可以使用双锁检测实现单例模式。
lock前缀的另一层意义是使得本线程工作内存中的volatile变量值立即写入到主内存中,并且使得其他线程共享的该volatile变量无效化,这样其他线程必须重新从主内存中读取变量值。

AOP 有哪些实现方式?

实现 AOP 的技术,主要分为两大类:
静态代理 - 指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
编译时编织(特殊编译器实现)
类加载时编织(特殊的类加载器实现)。
动态代理 - 在运行时在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。

  1. JDK 动态代理:通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口 。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类 。
  2. CGLIB 动态代理: 如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类 。 CGLIB ( Code Generation Library ),是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意, CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final ,那么它是无法使用 CGLIB 做动态代理的。

讲一讲HTTPS 的原理?

  1. 客户端请求 HTTPS 网址,然后连接到 server 的 443 端口 (HTTPS 默认端口,类似于 HTTP 的80端口)。
  2. 采用 HTTPS 协议的服务器必须要有一套数字 CA (Certification Authority)证书。颁发证书的同时会产生一个私钥和公钥。私钥由服务端自己保存,不可泄漏。公钥则是附带在证书的信息中,可以公 开的。证书本身也附带一个证书电子签名,这个签名用来验证证书的完整性和真实性,可以防止证 书被篡改。
  3. 服务器响应客户端请求,将证书传递给客户端,证书包含公钥和大量其他信息,比如证书颁发机构 信息,公司信息和证书有效期等。
  4. 客户端解析证书并对其进行验证。如果证书不是可信机构颁布,或者证书中的域名与实际域名不一 致,或者证书已经过期,就会向访问者显示一个警告,由其选择是否还要继续通信。
    如果证书没有问题,客户端就会从服务器证书中取出服务器的公钥A。然后客户端还会生成一个随 机码 KEY,并使用公钥A将其加密。
  5. 客户端把加密后的随机码 KEY 发送给服务器,作为后面对称加密的密钥。
  6. 服务器在收到随机码 KEY 之后会使用私钥B将其解密。经过以上这些步骤,客户端和服务器终于建立了安全连接,完美解决了对称加密的密钥泄露问题,接下来就可以用对称加密愉快地进行通信 了。
  7. 服务器使用密钥 (随机码 KEY)对数据进行对称加密并发送给客户端,客户端使用相同的密钥 (随机码 KEY)解密数据。
  8. 双方使用对称加密愉快地传输所有数据。

Cookie 和 Session 是如何配合的呢?

用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session ,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到服务器返回的 SessionID 信息后, 会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。
当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将
Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的
Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

Cookie和Session的区别?

作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型,一般情况下我们可以在
Session 中保持一些常用变量信息,比如说 UserId 等。
有效期不同,Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭或者 Session 超时都会失效。
隐私策略不同,Cookie 存储在客户端,比较容易遭到不法获取,早期有人将用户的登录名和密码存储在 Cookie 中导致信息被窃取;Session 存储在服务端,安全性相对 Cookie 要好一些。
存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。

数据库的join方式,区别;.数据库join的类型主要分为left join、right join、inner join

.left join 表示左边的表为主表,右边连接的表可以为NULL
如:

select a.id,a.name,b.name,b.city from user a left join liveregion b on a.cityId = b.id;

此处查询就可能出现a表的cityId为NULL时也能b表数据又为NULL的情况,即代表a表数据可以出现NULL 。 .right join 表示右边的表为主表,左边连接的表可以为NULL。同理如上。inner join 内连接 表示两个表均相关联的信息

B+Tree索引

是B-Tree的改进版本,同时也是数据库索引所采用的存储结构。数据都在叶子节点上,并且增加了顺序访问指针,每个叶子节点都指向相邻的叶子节点的地址。相比B-Tree来说,进行范围查找时只需要查找两个节点,进行遍历即可。

B-tree:

因为B树不管叶子节点还是非叶子节点,都会保存数据,这样导致在非叶子节点中能保存的指针数量变少(有些资料也称为扇出),指针少的情况下要保存大量数据,只能增加树的高度,导致IO操作变多,查询性能变低;

Hash:

虽然可以快速定位,但是没有顺序,IO复杂度高。
二叉树:树的高度不均匀,不能自平衡,查找效率跟数据有关(树的高度),并且IO代价高。

红黑树:

树的高度随着数据量增加而增加,IO代价高。有节点,相比之下B+Tree效率更高。

为什么官方建议使用自增长主键作为索引?

结合B+Tree的特点,自增主键是连续的,在插入过程中尽量减少页分裂,即使要进行页分裂,也只会分裂很少一部分。并且能减少数据的移动,每次插入都是插入到最后。总之就是减少分裂和移动的频率。

数据结构都了解那些?从这个问题我就有点儿懵,这么问的么

数组(Array)是有序的元素序列。 [1] 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 [1] 这些有序排列的同类数据元素的集合称为数组。

栈( Stack)
栈是一种特殊的线性表,它只能在一个表的一个固定端进行数据结点的插入和删除操作。栈按照后进先出的原则来存储数据,也就是说,先插入的数据将被压入栈底,最后插入的数据在栈顶,读出数据时,从栈顶开始逐个读出。栈在汇编语言程序中,经常用于重要数据的现场保护。栈中没有数据时,称为空栈。 [5]
队列(Queue)
队列和栈类似,也是一种特殊的线性表。和栈不同的是,队列只允许在表的一端进行插入操作,而在另一端进行删除操作。一般来说,进行插入操作的一端称为队尾,进行删除操作的一端称为队头。队列中没有元素时,称为空队列。 [5]
链表( Linked List)
链表是一种数据元素按照链式存储结构进行存储的数据结构,这种存储结构具有在物理上存在非连续的特点。链表由一系列数据结点构成,每个数据结点包括数据域和指针域两部分。其中,指针域保存了数据结构中下一个元素存放的地址。链表结构中数据元素的逻辑顺序是通过链表中的指针链接次序来实现的。 [5]
树( Tree)
树是典型的非线性结构,它是包括,2个结点的有穷集合K。在树结构中,有且仅有一个根结点,该结点没有前驱结点。在树结构中的其他结点都有且仅有一个前驱结点,而且可以有两个后继结点,m≥0。 [5]
图(Graph)
图是另一种非线性数据结构。在图结构中,数据结点一般称为顶点,而边是顶点的有序偶对。如果两个顶点之间存在一条边,那么就表示这两个顶点具有相邻关系。 [5]
堆(Heap)
堆是一种特殊的树形数据结构,一般讨论的堆都是二叉堆。堆的特点根结点的值是所有结点中最小的或者最大的,并且根结点的两个子树也是一个堆结构。 [5]
散列表(Hash)
散列表源自于散列函数(Hash function),其思想是如果在结构中存在关键字和T相等的记录,那么必定在F(T)的存储位置可以找到该记录,这样就可以不用进行比较操作而直接取得所查记录。 [5]

DNS和ARP的层

通过域名,最终得到该域名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53。
IP一般用IPV4或IPV6表示,为了让人们记住各个主机的ip地址,显然不现实,所以具有文字意义的域名就较好的解决了这个问题,顶级域名,其下可以在加上前缀构成一级域名,一级域名加上前缀,可构成二级域名,以此类推
MAC地址(Media Access Control Address),直译为媒体访问控制地址,也称为局域网地址(LAN Address),以太网地址(Ethernet Address)或物理地址(Physical Address),它是一个用来确认网上设备位置的地址。在OSI模型中,第三层网络层负责IP地址,第二层数据链接层则负责MAC地址。MAC地址用于在网络中唯一标示一个网卡,一台设备若有一或多个网卡,则每个网卡都需要并会有一个唯一的MAC地址。

相同:都是将一个给定的输入实体转换为另一个实体,DNS将域名转换为IP,而ARP则是将IP转换为物理地址。

异同:两者的输入对象不一致,并且两者在网络层次结构所在的位置不同,DNS工作在应用层,ARP工作在网络层。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值