2021/1/13 牛客百题总结

我不生产代码,我只是代码的搬运工

1.值传递和引用传递

代码:

public class SendValue{
    
    
	public String str="6";
	public static void main(String[] args) {
    
    
		SendValue sv=new SendValue();
		sv.change(sv.str);
		System.out.println(sv.str);
	}
	public void change(String str) {
    
    
		str="10";
	}
}

上述代码结果为:6

Java中都是值的传递,在此题中,首先要了解内存的分配机制。

public String str="6"

这j句话内存分配机制是:
首先在栈中新开辟一个对String类的对象的引用变量str

然后在栈中查找是否有值为"6"的地址

如果有,则将其赋予给新创建的str

如果没有,则堆中新创建一个String对象"6",命名为newObj,栈中新创建一个空间,命名为newStack,newStack是用来保存newObj地址的,最后,str指向newStack。

而在本题过程中:

首先,将str形参地址传入到change函数

但是,由于Java都是值传递的,所以相当于在栈中新建了一个k对象,这个k对象保存的地址与str的地址是相同的。

接着,k="10"语句开始执行,查找栈中并没有“10”的地址,因此新建,并将地址返回给k

这个时候,其实k与str已经没有关系了,因为str指向的是"6",而k指向的是"10",结果当然也是不变的。
在这里插入图片描述

2.String拼接生成对象数量问题

String test="javaandpython"; 
String str1="java"; 
String str2="and"; 
String str3="python"; 
System. out. println(test=="java"+"and"+"python"): 
System. out. println(test ==str1 + str2 + str3);

对于上面这段代码,结果是true false

这是因为字符串字面量拼接操作是在Java编译器编译期间就执行了,也就是直接把"java"、“and"和"python"这三个字面量进行”+“操作得到一个"javaandpython” 常量,并且直接将这个常量放入字符串池中.

而字符串引用的"+"运算是在Java运行期间执行的,即str1 + str2 + str3在程序执行期间才会进行计算,它会在堆内存中重新创建一个拼接后的字符串对象。

且在字符串常量池中也会有str1,str2与str3,这里创建多少个新的对象与原来字符串常量池中有没有str1\str2\str3有关,如果之前存在就不会创建新的对象。

总结来说就是:字面量"+“拼接是在编译期间进行的,拼接后的字符串存放在字符串池中;而字符串引用的”+"拼接运算实在运行时进行的,新创建的字符串存放在堆中。

3.Hibernate的一些知识

1、什么是延迟加载?

定义:

延迟加载(lazy load)是Hibernate3 关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的。

就是只有当真正需要数据时,才真正的执行数据加载操作。延迟加载是 hibernate 中用于提高查询效率的一种措施,它的对立面是 立即加载。

2、如何实现延迟加载?

Hibernate 2 实现延迟加载有 2 种方式:

  • 实体对象
  • 集合

Hibernate 3 又引入了一种新的加载方式:属性的延迟加载

一般使用load()的方法来实现延迟加载:

当调用load方法加载对象时,返回***对象,等到真正用到对象的内容时才发出sql语句

3、Hibernate 其他介绍

Hibernate 使用 Java 反射机制,而不是字节码增强程序来实现透明性

Hibernate 的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。

4、优化 Hibernate 所鼓励的 7 大措施

  1. 尽量使用多对一,避免使用单项一对多
  2. 灵活使用单向一对多
  3. 不用一对一,使用多对一代替一对一
  4. 配置对象缓存,不使用集合缓存
  5. 一对多使用Bag ,多对一使用Set
  6. 继承使用显示多态 HQL:from object polymorphism=“exlicit” 避免查处所有对象
  7. 消除大表,使用二级缓存

4.Object类中的一些方法

在这里插入图片描述

5.Synchronized和volatile特性

synchronized保证三大性:原子性,有序性,可见性

volatile保证:有序性,可见性

  1. 禁止了指令重排
  2. 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量值,这个新值对其他线程是立即可见的
  3. 不保证原子性(线程不安全)

synchronized关键字和volatile关键字比较

  1. volatile关键字是线程同步的轻量级实现,所以volatile性能肯定比synchronized关键字要好。
  2. 但是volatile关键字只能用于变量而synchronized关键字可以修饰方法以及代码块。
  3. synchronized关键字在JavaSE1.6之后进行了主要包括为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁以及其它各种优化之后执行效率有了显著提升,实际开发中使用synchronized 关键字的场景还是更多一些。
  4. 多线程访问volatile关键字不会发生阻塞,而synchronized关键字可能会发生阻塞
  5. volatile关键字能保证数据的可见性,但不能保证数据的原子性。synchronized关键字两者都能保证。
  6. volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized关键字解决的是多个线程之间访问资源的同步性。

6.抽象方法和抽象类的一些注意事项

  1. 抽象类不能被实例化,实例化的工作应该交由它的子类来完成,它只需要有一个引用即可。
  2. 抽象方法必须由子类来进行重写。
  3. 只要包含一个抽象方法的类,该类必须要定义成抽象类,不管是否还包含有其他方法。
  4. 抽象类中可以包含具体的方法,当然也可以不包含抽象方法。
  5. abstract不能与final并列修饰同一个类。
  6. abstract 不能与private、static、final或native并列修饰同一个方法。
  7. 抽象方法不允许有方法体和大括号,以分号结束.

7.HashMap和Hashtable的区别

  1. 线程是否安全: HashMap 是⾮线程安全的,HashTable 是线程安全的;HashTable 内部的⽅法 基本都经过synchronized 修饰。(如果你要保证线程安全的话就使⽤ ConcurrentHashMap 吧!)

  2. 效率: 因为线程安全的问题,HashMap 要⽐ HashTable 效率⾼⼀点。另外,HashTable 基本被
    淘汰,不要在代码中使⽤它;

  3. 对Null key 和Null value的⽀持: HashMap 中,null 可以作为键,这样的键只有⼀个,可以
    有⼀个或多个键所对应的值为 null。但是在 HashTable 中 put 进的键值只要有⼀个 null, 直接抛出
    NullPointerException。

  4. 初始容量⼤⼩和每次扩充容量⼤⼩的不同 :创建时如果不指定容量初始值,Hashtable 默认的初始⼤⼩为11,之后每 次扩充,容量变为原来的2n+1。HashMap 默认的初始化⼤⼩为16。之后每次扩充,容量变为原来的2倍。创建时如果给定了容量初始值,那么 Hashtable 会直接使⽤你给定的⼤⼩,⽽ HashMap 会将其扩充为2的幂次⽅⼤⼩.

  5. 底层数据结构: JDK1.8 以后的 HashMap在解决哈希冲突时有了j较⼤的变化,当链表⻓度⼤于阈值(默认为8)时,将链表转化为红⿊树,以减少搜索时间。Hashtable没有这样的机制。

  6. 继承的父类不同:Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。但二者都实现了Map接口。

8.try-catch-finally问题

  • 用try-catch 捕获异常;
  • 用try-finally 清除异常;
  • 用try-catch-finally 处理所有的异常. 三者选一种即可

9.Statement,PreparedStatement,CallableStatement有关知识

  1. Statement、PreparedStatement和CallableStatement都是接口(interface)

  2. Statement继承自Wrapper、PreparedStatement继承自Statement、CallableStatement继承自PreparedStatement

  3. Statement接口提供了执行语句和获取结果的基本方法;
    PreparedStatement接口添加了处理 IN 参数的方法;
    CallableStatement接口添加了处理 OUT 参数的方法。

  4. ①Statement: 普通的不带参的查询SQL;支持批量更新,批量删除;
    ②PreparedStatement: 可变参数的SQL,编译一次,执行多次,效率高; 安全性好,有效防止Sql注入等问题; 支持批量更新,批量删除;
    ③CallableStatement: 继承自PreparedStatement,支持带参数的SQL操作; 支持调用存储过程,提供了对输出和输入/输出参数(INOUT)的支持;

  5. PreparedStatement是预编译的,使用PreparedStatement有几个好处:
    ①在执行可变参数的一条SQL时,PreparedStatement比Statement的效率高,因为DBMS预编译一条SQL当然会比多次编译一条SQL的效率要高。
    ②安全性好,有效防止Sql注入等问题。
    ③对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;
    ④代码的可读性和可维护性。

10.Java中的四类八种基本数据类型:

  1. 第一类:整数类型 byte short int long
  2. 第二类:浮点型 float double
  3. 第三类:逻辑型 boolean(它只有两个值可取true false)
  4. 第四类:字符型 char

11.两同两小一大原则

方法名相同,参数类型相同
子类返回类型小于等于父类方法返回类型,
子类抛出异常小于等于父类方法抛出异常,
子类访问权限大于等于父类方法访问权限。

12.Java三大注释

  1. Java三大注解分别是@Override @Deprecated @Suppresswarnings
  2. @Override 注解表名子类中覆盖了超类中的某个方法,如果写错了覆盖形式,编译器会报错
  3. @Deprecated 表明不希望别人在以后使用这个类,方法,变量等等
  4. @Suppresswarnings 达到抑制编译器产生警告的目的,但是不建议使用,因为后期编码人员看不懂编译器提示的警告,不能更好的选择更好的类去完成任务

13.抽象类和接口的区别:

  1. 抽象类可以有构造方法,接口中不能有构造方法。
  2. 抽象类中可以有普通成员变量,接口中没有普通成员变量
  3. 抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
  4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
  5. 抽象类中可以包含静态方法,接口中不能包含静态方法
  6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。

14.会话跟踪

会话跟踪是一种灵活、轻便的机制,它使Web上的状态编程变为可能。

HTTP是一种无状态协议,每当用户发出请求时,服务器就会做出响应,客户端与服务器之间的联系是离散的、非连续的。当用户在同一网站的多个页面之间转换时,根本无法确定是否是同一个客户,会话跟踪技术就可以解决这个问题。当一个客户在多个页面间切换时,服务器会保存该用户的信息。

有四种方法可以实现会话跟踪技术:URL重写、隐藏表单域、Cookie、Session。

  1. 隐藏表单域:非常适合不需要大量数据存储的会话应用。
  2. URL 重写:URL 可以在后面附加参数,和服务器的请求一起发送,这些参数为名字/值对。
  3. Cookie:一个 Cookie 是一个小的,已命名数据元素。服务器使用 SET-Cookie 头标将它作为HTTP响应的一部分传送到客户端,客户端被请求保存 Cookie 值,在对同一服务器的后续请求使用一个Cookie头标将之返回到服务器。与其它技术比较,Cookie 的一个优点是在浏览器会话结束后,甚至在客户端计算机重启后它仍可以保留其值
  4. Session:使用 setAttribute(String str,Object obj)方法将对象捆绑到一个会话

猜你喜欢

转载自blog.csdn.net/qq_52212721/article/details/112545613
今日推荐