Java对象的创建方式以及对象的引用
日子就是这么的庸常,却有细碎的事物,如太阳碎碎的光芒,洒落其上
Java创建对象有几种方式
new创建新对象
new创建我们就很熟悉了,像Person p = new Person();等等
通过反射机制
这种创建对象的方式就是当我们编译时不知道要创建什么对象时,只有在运行时才能确定,这个时候就可以通过反射来创建对象
采用clone机制
clone复制机制一般分为浅拷贝和深拷贝
-
浅克隆:原对象和克隆对象不同,但对象内的成员引用相同
-
深克隆:原对象和克隆对象不同,且对象内的成员引用也不同
不同:不是同一个对象,所占内存地址不同
成员引用:类中为引用类型的成员
通过序列化机制
“序列化”是一种把对象的状态转化成字节流的机制,“反序列”是其相反的过程,把序列化成的字节流用来在内存中重新创建一个实际的Java对象。这个机制被用来“持久化”对象。通过对象序列化,可以方便的实现对象的持久化储存以及在网络上的传输
Java对象的引用----强软弱虚
-
强引用
强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收,使用方式:
String str = new String("str"); System.out.println(str) // str
-
软引用
软引用在程序内存不足时,会被回收,使用方式:
// 注意:wrf这个引用也是强引用,他是指向SoftReference这个对象的 // 这里的软引用指的是指向new String("str")的引用,也就是SoftReference类中的T SoftReference<String> wrf = new SoftReference<String>(new String("str"));
可用场景:创建缓存的时候,创建的对象放进缓存中,当内存不足时,JVM就会回收早先创建的对象
-
弱引用
弱引用就是只要JVM垃圾回收器发现了它,就会回收,使用方式:
WeakReference<String> wrf = new WeakReference<String>(str);
可用场景: Java源码中的
java.util.WeakHashMap
中的key
就是使用弱引用,我的理解就是,一旦我不需要某个引用,JVM会自动帮我处理它,这样我就不需要做其它操作。 -
虚引用
虚引用的回收机制跟弱引用差不多,但是它被回收之前,会被放入
ReferenceQueue
中。注意 哦,其它引用是被JVM回收后才被传入ReferenceQueue
中的。由于这个机制,所以虚引用大多 被用于引用销毁前的处理工作。还有就是,虚引用创建的时候,必须带有ReferenceQueue
, 使用例子:PhantomReference<String> prf = new PhantomReference<String> (new String("str"),new ReferenceQueue<>());
可用场景: 对象销毁前的一些操作,比如说资源释放等。 Object.finalize() 虽然也可以做这 类动作,但是这个方式即不安全又低效
上诉所说的几类引用,都是指对象本身的引用,而不是指Reference的四个子类的引用 (SoftReference等)。
二分查找
题目:俄罗斯套娃信封问题
难度:🌟🌟🌟🌟🌟
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/russian-doll-envelopes
给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
注意:不允许旋转信封。
示例 1:
输入:envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出:3
解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。
示例 2:
输入:envelopes = [[1,1],[1,1],[1,1]]
输出:1
请先思考!!!!
|||||||||||
|||||||||||
|||||||||||
|||||||||||
|||||||||||
|||||||||||
|||||||||||
答答答答答答答答答答答
案案案案案案案案案案案
往往往往往往往往往往往
下下下下下下下下下下下
翻翻翻翻翻翻翻翻翻翻翻
|||||||||||
|||||||||||
|||||||||||
|||||||||||
|||||||||||
|||||||||||
|||||||||||
class Solution {
public int maxEnvelopes(int[][] envelopes) {
// 如果我们控制了一列,那么这个问题就会变成找一维数组的最长子序列的问题
// 加入我们控制宽度w按照省升序的方式排序,如果宽度w相同,那么就将高度h降序排序
// 排序完就成了 [2,3],[5,4],[6,7],[6,4]
// 此时我们就可以求高度h的最长子序列就可以找到问题的答案
// 排序,这个地方采用了Arrays.sort()方法进行自定义排序
Arrays.sort(envelopes, new Comparator<int[]>() {
@Override
public int compare(int[] a, int[] b) {
// 如果w相同就按照h的降序排序
return a[0] == b[0] ? b[1] - a[1] : a[0] - b[0];
}
});
// 拍完序之后就h列作为新的数组来求LIS序列
int[] arr = new int[envelopes.length];
for( int i = 0 ; i < envelopes.length ; i++){
arr[i] = envelopes[i][1];
}
// 计算LIS的个数
return arrayLISNum(arr);
}
// 求最大的自序列
public int arrayLISNum(int[] arr){
int[] maxArr = new int[arr.length];
int res = 0;
for(int num : arr){
int x = 0;
// y就是代表maxArr数组的长度也就是res也是代表maxArr数组的长度
int y = res;
while(x < y){
int mid = (x + y) >> 1;
if(maxArr[mid] >= num){
y = mid;
}else {
x = mid + 1;
}
}
maxArr[x] = num;
if(y == res){
res++;
}
}
return res;
}
}
题解:
这个问题的难点就在于怎么进行排序来求出LIS序列,一般遇到问题的时候我们就要思考,一维数组我们很好控制,那么能不能将二维数组转换为一维数组来进行判断,首先我们就想到,要想将二维数组的问题转换为一维数组那么我们就要控制好一个纬度,然后操作另一个纬度,在本次俄罗斯套娃问题中就很好的体现,我们控制好宽度或者高度然后去操作高度或者宽度,就可以复杂的问题简单化,具体思路已经在注释上体现了。