X32专项练习部分12

4种引用类型

	/*
    下面有关java的引用类型,说法正确的有?
    正确答案: A B C D
    对于一个对象来说,只要有强引用的存在,它就会一直存在于内存中
    如果一个对象仅持有虚引用,那么它就和没有任何引用一样,
        在任何时候都可能被垃圾回收器回收。
    如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;
        如果内存空间不足了,就会回收这些对象的内存
    一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的空间

    下面是4种引用类型

    强引用
    Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收
    obj = null; //手动置null
    只要强引用存在,垃圾回收器将永远不会回收被引用的对象
    哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收
    如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null
    这样一来,JVM就可以适时的回收对象了

    软引用
    软引用是用来描述一些非必需但仍有用的对象
    在内存足够的时候,软引用对象不会被回收,
    只有在内存不足时,系统则会回收软引用对象
    如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常
    这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等
    在JDK1.2之后,用java.lang.ref.SoftReference类来表示软引用

    弱引用
    弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收
    那些被弱引用关联的对象都会被回收
    在JDK1.2之后,用java.lang.ref.WeakReference来表示弱引用
    
    虚引用
    虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用
    那么它就和没有任何引用一样,它随时可能会被回收,在JDK1.2之后,用PhantomReference类来表示
    通过查看这个类的源码,发现它只有一个构造函数和一个 get() 方法
    而且它的 get() 方法仅仅是返回一个null,也就是说将永远无法通过虚引用来获取对象
    虚引用必须要和 ReferenceQueue 引用队列一起使用
     */

线程锁释放

	/*
    下列哪些操作会使线程释放锁资源?
    正确答案: B C
    sleep()
    wait()
    join()
    yield()

    sleep会使当前线程睡眠指定时间,不释放锁
    yield会使当前线程重回到可执行状态,等待cpu的调度,不释放锁
    wait会使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll唤醒时进入可执行状态
    join当前线程调用thread.join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁
     */

for循环执行顺序

class Test4 {
    static boolean foo(char c) {
        System.out.print(c); // ABDCBDCB
        return true;
    }

    public static void main(String[] args) {
        int i = 0;
        for (foo('A'); foo('B') && (i < 2); foo('C')) {
            i++;
            foo('D');
        }
    }
    /*
    考察的相当于for循环执行顺序

    其实foo(‘A’);就是初始化条件,只会执行一次,所以第一个打印的肯定是A
    因为i=0;循环条件是i<2
    由此可知循环i等于2的时候就会停止循环
    所有0<2满足条件
    接着会输出B,然后执行i++

    i就变成1了,再输出D
    再最后输出C,一次循环后的结果是:ABDC

    第二次循环的开始是foo(‘A’);是初始条件所以不会执行,
    直接从foo(‘B’)开始,输出B,
    然后i为1,且小于2,此时循环体内再次执行i++
    i的值为2了,再次输出D,最后输出C 
    第二次循环输出:BDC 
    
    然后循环再次执行for(foo(‘A’);foo(‘B’)&&(i<2);foo(‘C’)) 
    直接输出B,i的值在第二轮循环后的值变成了2,2<2不成立,终止循环,输出B
     */
}

Integer类的常用方法

public static void main(String[] args) {
        int a = Integer.parseInt("1024");

        int b = Integer.valueOf("1024").intValue();

        /*
        a是整数类型变量,b是整数类对象
        a是整数类对象,b是整数类型变量
        a和b都是整数类对象并且它们的值相等
        a和b都是整数类型变量并且它们的值相等
         */

        System.out.println(judgeTypeInteger(a)); // true
        System.out.println(judgeTypeInteger(b)); // true
        System.out.println(a == b); // true

        /*
        intValue()是把Integer对象类型变成int的基础数据类型
        parseInt()是把String 变成int的基础数据类型
        valueof()是把String 转化成Integer对象类型,现在JDK版本支持自动装箱拆箱了

        parseInt得到的是基础数据类型int,
        valueof得到的是装箱数据类型Integer,
        然后再通过valueInt转换成int,所以选择D
         */
}

三角函数

		double d = Math.cos(42);
        // double d1 = Math.cosine(42); // cosine方法不存在
        double d2 = Math.cos(Math.toRadians(42));
        double d3 = Math.cos(Math.toDegrees(42));
        System.out.println(d + " " + d2 + " " + d3);
        // -0.39998531498835127 0.7431448254773942 0.9993069281930212
        // 科学计算器算出的结果是 0.74314482547739423501469704897426

        /*
        Math.cos为计算弧度的余弦值
        Math.toRadians函数讲角度转换为弧度
        toDegrees()是将弧度转换为角度
         */

GC垃圾回收机制

/*
以下说法正确的是

垃圾回收线程的优先级很高,以保证不再使用的内存将被及时回收
垃圾收集允许程序开发者明确指定释放哪一个对象
垃圾回收机制保证了JAVA程序不会出现内存溢出
进入”Dead”状态的线程将被垃圾回收器回收
以上都不对

正确答案:E

A:垃圾回收在jvm中优先级相当相当低
当程序运行时,至少会有两个线程开启启动,一个是我们的主线程
一个时垃圾回收线程,垃圾回收线程的priority(优先级)较低

B:垃圾收集器(GC)程序开发者只能推荐JVM进行回收,但何时回收,回收哪些,程序员不能控制
垃圾回收器会对我们使用的对象进行监视,当一个对象长时间不使用时
垃圾回收器会在空闲的时候(不定时)对对象进行回收,释放内存空间
程序员是不可以显示的调用垃圾回收器回收内存的
但是可以使用System.gc()方法建议垃圾回收器进行回收,但是垃圾回收器不一定会执行

C:垃圾回收机制只是回收不再使用的JVM内存,如果程序有严重BUG,照样内存溢出
D:进入DEAD的线程,它还可以恢复,GC不会回收
进入dead的线程最后会调用finilized方法,有可能是dead线程重新复活。所以d错
 */

值传递开辟内存空间

/*
下面这段java代码,当 T 分别是引用类型和值类型的时候
分别产生了多少个T对象和T类型的值()

T t = new T();(值类型时:T t;)
Func(t);
Func 定义如下:
public void Func(T t) {  }

正确答案: D
1  1
2  1
2  2
1  2

引用类型作为函数的参数时,复制的是引用的地址,不会产生一个新的T
而如果T是值类型,其作为函数实参时会复制其值,也就是产生了一个新的T
所以D选项正确

值类型即八大基础类型,基础类型在使用时是从常量池中获取
更严谨的而言其实是在-128~127之间 使用时是从常量池中获取,那么在使用的时候将常量池中的地址重复利用
但是在限制范围之外,得到的地址就会发生变化 代码为证
 */

class Test7 {
    public static void main(String[] args) {
        int x1 = 127;
        int x2 = 129;

        int identityHashCode = System.identityHashCode(x1);
        System.out.println("传递之前:x1 identityHashCode = "+identityHashCode);

        identityHashCode = System.identityHashCode(x2);
        System.out.println("传递之前:x2 identityHashCode = "+identityHashCode);

        System.out.println("-----------------------------------------");
        method(x1);
        method(x2);
    }

    public static void method(int x) {
        int identityHashCode = System.identityHashCode(x);
        System.out.println("传递之后:x identityHashCode = "+identityHashCode);
    }
    /*
    传递之前:x1 identityHashCode = 460141958
    传递之前:x2 identityHashCode = 1163157884
    -----------------------------------------
    传递之后:x identityHashCode = 460141958
    传递之后:x identityHashCode = 1956725890

    x1前后得到的hashCode相同
    x2前后得到的hashCode不相同

    总之,我还是认为值类型的不能称之为对象,虽然超过缓存范围限制时重新开辟了空间,
    但是不能与引用类型混为一谈
    我坚持值类型传递创建了0个对象,开辟了2个内存地址
     */
}

Java创建对象的5种方式

/*
Java有5种方式来创建对象:
1、使用 new 关键字(最常用): ObjectName obj = new ObjectName();
2、使用反射的Class类的newInstance()方法: ObjectName obj = ObjectName.class.newInstance();
3、使用反射的Constructor类的newInstance()方法:
    ObjectName obj = ObjectName.class.getConstructor.newInstance();
4、使用对象克隆clone()方法: ObjectName obj = obj.clone();
5、使用反序列化(ObjectInputStream)的readObject()方法:
    try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_NAME))) {
        ObjectName obj = ois.readObject();
    }
 */

总目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muskfans

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值