HashSet,HastMap都不允许重复,在存放数据时会先调用HoahCode来判断和之前的数据是否重复,如果和其他对象的hashCode值一样就会再调用equals来判断是否是一个对应,equals如果也一样的话就断定是一个值。
可以使用 int Objects.hash(args...)函数来实现hashCode,参数一般填为自己的所有字段。
System.gc(),建议vm进行垃圾回收的函数。
垃圾回收时,会从所有的GC Root作为是起始点,从这些点开始,垃圾回收器会尝试查找和访问堆上的对象。换句话说,从GC Root可以直接或间接地引用到的对象都被认为是"活动的",也就是还在使用中。而那些从GC Root无法访问到的对象则可能是垃圾,它们可能会在下一次垃圾回收时被清除。
以下是常见的GC Root:
虚拟机栈引用的对象:当前线程中的局部变量、参数、返回值等都属于这一类。
方法区中静态属性引用的对象:也就是所有的类级别的静态变量。
方法区中常量引用的对象:例如字符串常量池中的引用。
本地方法栈中JNI(即通常所说的Native方法)引用的对象。
活跃的线程本身。
所有被同步锁synchronized持有的对象。
各种引用的区别就是垃圾回收的时候,处理的方式不一样。
普通创建的对象就是硬引用,除非引用变量在栈中被销毁,否则不会被回收。
一般作为缓存使用。
当系统内存充足时,持有软引用的对象不会被垃圾收集器回收。
当系统内存不足或即将耗尽时,持有软引用的对象会被垃圾收集器考虑回收,即使这个对象还有软引用指向它。
举例:
想要创建一个图像的缓存。你不希望一直持有这些图像,以防止占用太多内存,但当内存充足时,你也不希望它们被频繁地回收和重新加载。这时,软引用是一个很好的选择:
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
public class ImageCache {
private Map> cache = new HashMap<>();
public Image getImage(String path) {
SoftReference softRef = cache.get(path);
if (softRef != null) {
Image image = softRef.get();
if (image != null) {
return image; // 使用缓存中的图像
}
}
// 缓存中没有图像或图像已被回收,重新加载它
Image image = loadImageFromDisk(path);
cache.put(path, new SoftReference<>(image));
return image;
}
private Image loadImageFromDisk(String path) {
// 从磁盘加载图像的代码
// ...
return new Image();
}
// Image类的定义,为简洁起见,此处省略实际实现
private static class Image {}
}
四种:继承Thread类,实现Runnable接口,
ThreadLocal只能放入一个对象和取出一个对象,但是很神奇的是,同一个线程中get出的对象是相同的。
static ThreadLocal
Spring中Bean默认作用域是单利的,spring中的一个类加上@Component时,这个类有一个属性为a,a默认为0,第一个通过@AutoWrite获取时设置a为1,第二次通过@AutoWrite获取这个类的示例时时a的值是1。
可以用过@Bean与@Scope("prototype")来设置作用域。
Spring 的常用作用域:
MVC 是 Model-View-Controller 的缩写,它是一种设计模式。MVC 将应用程序逻辑分为三个互相关联的组件,以实现模块化和更容易的管理。以下是这三个组件的解释:
Model(模型):这是应用程序的数据部分。它包含所有的业务逻辑、数据和规则。模型是独立于视图和控制器的,这意味着模型不知道用户界面如何显示数据。
View(视图):这是用户看到和与之互动的部分。它负责展示模型的数据。当模型中的数据发生变化时,视图会相应地更新。
Controller(控制器):控制器是模型和视图之间的接口。它接收用户的输入并决定如何处理。基于用户的行为,控制器可以请求模型进行更改或更新,或者更改视图的表示。
前后端分离的现在,后端已经没有View层了。
Server、Mapper,domain等层属于Model类,Controller层属于controller类。
注意:如果A变量的构造函数需要B,B的构造函数需要A,这种是误解的。
如果两个Java类在它们的构造函数中相互依赖,那么这会导致问题,因为无法在初始化一个类的同时初始化另一个类。
但是,Spring框架确实提供了处理循环依赖的机制。以下是Spring如何解决这个问题的:
字段注入:如你所说,如果A类有一个B类型的字段,并且这个字段是通过Spring注入的,同时B类也有一个A类型的字段并且这个字段是通过Spring注入的,那么Spring可以解决这种依赖关系。这是因为Spring首先创建了A和B的实例,然后再为它们的字段注入依赖。
Setter方法注入:与字段注入类似,使用setter方法注入也可以解决循环依赖。Spring首先创建对象实例,然后使用setter方法为对象注入依赖。
这里举例A依赖B。B依赖A:
初始化A时,会先创建A类原始的Bean(未填充属性的),然后把这个Bean放入二级缓存,并在三级缓存中创建A的工厂对象。
填充A的属性时,发现需要B,于是就创建B。
创建B时发现需要A,Spring会从一级缓存中查找A,找不到就去二级缓存中查找A,发现二级有A的早期实例,就会拿这个填充。
这时B创建完了,就用B填充A。
三级缓存中的工厂对象是在bean实例化但还未完全初始化(如属性填充)时放进去的。
三级工厂就是为了返回未初始化完成的Bean而创建。三级工厂返回的Bean会放入二级缓存。
这么做是为了不影响二级中的Bean初始化,二级中的Bean初始化完成之后要直接放入一级缓存。
工厂返回的Bean与二级缓存中的Bean是一样的,同一个引用。
当Spring容器开始初始化一个bean(例如A)时,它会首先调用A的构造方法来实例化它。
然后Spring会进行属性注入、执行初始化方法等其他初始化步骤。
一旦bean完全初始化,它会直接放入一级缓存,这时它已经是一个完全初始化的单例bean,可以被其他bean或应用代码引用。
这两个都是做Bean注入用的,@Resource并不是Spring的注解,他的包是javax.annotation.Resource需要导入,但是Spring支持改注解的注入。
共同点:都可以写在字段和setter方法上,两者如果都写在字段上。
@Autowired默认按照类型(byType)装配依赖对象。
默认情况下他要求依赖的对象必须存在,如果允许为null,可以设置他的required属性为false。
如果我们想按名称(byName)来装配,可以结合@Qualifier注解一起使用,@Qualifier注解来指定名称。
@Resource默认按照名称(ByName)装配依赖对象,由j2ee提供。
@Resource有两个重要的属性,name和type。
Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。
需要额外添加依赖:
org.springframework.boot
spring-boot-context-indexer
这是@Indexed的依赖,添加这个依赖之后可以提高Springboot的启动速度。
添加这个依赖编译项目(使用Maven的install)后会自动把:@Component,@Indexed,@Controller,@Service,@Repository这些相关的额注解标注的类的路径自动包含在“target/META-INF/spring-components”文件中,启动时提高速度。
@Import注解的作用:让Spring容器从其他指定的配置类中加载被@Bean修饰过的方法。
public class Person {
...
}
public class Address {
...
}
@Configuration
public class MainConfig {
@Bean
public Person john() {
return new Person("John");
}
}
@Configuration
public class AdditionalConfig {
@Bean
public Address newYorkAddress() {
return new Address("New York");
}
}
@Configuration
@Import({MainConfig.class, AdditionalConfig.class})
public class CombinedConfig {
@Autowired
private Person john;
@Autowired
private Address newYorkAddress;
@Bean
public String johnsAddressInfo() {
return john.getName() + " lives in " + newYorkAddress.getCity();
}
}
上面代码中:
CombinedConfig类上的@Import注解使MainConfig和AdditionalConfig中所有用@Bean标注的方法的返回值被注册到Spring容器中。
当Spring启动并处理CombinedConfig时,它不仅会注册CombinedConfig中定义的beans,还会注册MainConfig和AdditionalConfig中定义的beans。这正是@Import注解的主要目的。
@RestController
public class HelloController {
@GetMapping("/restController")
public User test() {
return new User();
}
}
@Controller
public class HelloController {
@GetMapping("/controller")
public User test() {
return new User();
}
}
@RestController:
它是一个组合注解,等同于 @Controller 和 @ResponseBody 的组合。
它意味着这个控制器的所有方法的返回值都将自动序列化为 JSON 或其他媒体类型,并作为 HTTP 响应的体返回。因此,当你访问 http://localhost/restController时,在浏览器中直接看到的是 xxx 对象的 JSON 表示。
问:@RequestMapping("/hello") public String Hello(){ return "hello"; } }:返回字符串时:RestController不是返回的json格式吗,为什么,为什么浏览器的网络相应中返回的是hello,而不是“hello”,为什么hello会直接输出到页面上,RestController什么时候返回json什么时候返回xml
答:
为什么返回的是 "hello" 而不是 “"hello"”?
当你返回一个简单的字符串时,Spring MVC 会直接将这个字符串作为响应体返回,而不会将它视为一个 JSON 字符串值。所以,返回的就是 hello 而不是 JSON 格式的 "hello"。
为什么 "hello" 会直接输出到页面上?
这是因为默认的 Content-Type 是 text/plain。所以浏览器会把它当作纯文本来处理,并直接显示。
@RestController 何时返回 JSON 和何时返回 XML?
@RestController 会基于请求的 Accept 头和项目的依赖来确定返回什么格式的数据。
如果请求头包含 Accept: application/json 并且你的项目中有合适的 JSON 库(如 Jackson),那么默认返回的是 JSON 格式。
如果请求头包含 Accept: application/xml 并且你的项目中有 XML 绑定库,那么会返回 XML 格式。
如果方法返回一个对象或集合,并且接受的请求头是 Accept: application/json,则 @RestController 通常会返回 JSON 格式的数据。如果没有特定的 Accept 头或者接受多种内容类型,那么通常默认返回的是 JSON,前提是你的项目中有相关的 JSON 库。
@Controller:
当你在方法上没有使用 @ResponseBody 注解时,@Controller 注解的方法默认返回的是一个视图(view)的名字(通常用于模板引擎,例如 Thymeleaf, JSP 等)。
http://localhost:86/controller 时方法返回的是一个 User 对象。但因为你没有指定视图名,也没有使用 @ResponseBody,Spring 将尝试查找一个与 User 对象名匹配的视图,这通常不是你想要的。
这里的视图,指的是JSP那种。
REST风格:
在REST风格中,HTTP动词(方法)如 GET, POST, PUT, DELETE 通常有以下的含义和约定:
GET:
POST:
Location
头,指示新创建资源的URI。PUT:
DELETE:
REST风格使用多个参数:@GetMapping("/api/users/{userId}/orders/{orderId}");,对应的普通请求链接:“/api/userOrder?userId=123&orderId=456”。
普通风格:
GET /getUser?id=1:用来查询。
REST 描述了一种理论上的架构风格和一组原则,而当一个 Web 服务实际遵循这些原则时,我们称其为 RESTful。
什么是索引:
排好序可以快速查找的数据结构。
索引的优势与劣势:
优势:提高数据检索的效率,降低数据库的io成本,通过索引排序能够大大减少CPU的消耗(因为索引已经是排好序的)。
劣势:需要经常增删的表不建议使用索引,因为更新表的数据时,也会更新索引数据,会降低更新的速度。
索引的分类:
主键索引,单值索引,唯一索引,复合索引。
单值索引和唯一索引的区别就是,单值索引允许重复,单一索引不允许。
对象间的一种一对多的关系,当一个对象的状态发生改变时,所有依赖它的对象都会通知并自动更新。
一般主线程中一个while(1)循环,不停的判断子线程的状态,状态变化时通知其它子线程,比如任务的撤销。
工厂根据传递过来的参数决定生产哪个对象,Spring中可以通过getBean方法获取对象的时候根据id或者name获取,就是简单的工厂模式。
将一个类的接口转换为客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
用来动态的为一个对象添加新的功能,装饰者模式是一种用于替代继承的技术,无需通过继承增加子类就能扩展对象的新功能,使用对象的关联关系替代继承关系,更加灵活,同时避免体系的快速膨胀。
Spring AOP的实现就是代理模式。
策略模式对应于解决某一个问题的一个算法族,允许用户从该算法族中任选一个算法解决莫一问题,同时可以方便的更换算法或者增加新的算法,并且由客户端决定使用哪个算法。