一些基础知识

本文深入讲解Java中的类成员访问修饰符、基本数据类型、浮点数精度、字符串处理、垃圾回收机制等核心概念,同时探讨了字符串常量池的工作原理及不同JDK版本间的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类修饰符
类的成员不写访问修饰时默认为default。默认对于同一个包中的其他类相当于公开(public),对于不是同一个包中的其他类相当于私有(private)。受保护(protected)对子类相当于公开,对不是同一包中的没有父子关系的类相当于私有。Java中,外部类的修饰符只能是public或默认

8个基本类型: byte、short、int、long、float、double、char、boolean

float的指数位有8位,而double的指数位有11位

float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用java.math.BigDecimal。使用BigDecimal并且一定要用String来够造。

装箱后对象是引用类型, 引用类型比较时使用的是指针,

        Integer a = new Integer(3);
        Integer b = 3;                  // 将3自动装箱成Integer类型
        int c = 3;
        System.out.println(a == b);     // false 两个引用没有引用同一对象
        System.out.println(a == c);     // true a自动拆箱成int类型再和c比较         
    **//四舍五入的原理是在参数上加0.5然后进行下取整。**
    System.out.println(Math.round(11.5));//12
    System.out.println(Math.round(-11.5));// -11 

StringBuilder 单线程下使用,
StringBuffer 多线程下使用.


intern方法

当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确
定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。

  1. 引号声明: 引号声明的字符串都是会直接在字符串常量池, 如:String s4 = “11”
  2. new String对象,是在堆空间中放置的, 通过调用intern(),方法,再讲对象同步到字符串常量(pool)中.
  3. intern()比不使用intern()消耗的内存更少。
//显示声明的:String s4 = "11"; 直接去常量池中创建对象
String s = new String("abc") //直接创建一个String对象


//经典DEMO
String s = new String("1");   //生成了常量池中的“1” 和堆空间中的字符串对象。
s.intern();  //s对象去常量池中寻找后发现"1"已经存在于常量池中了
String s2 = "1";   //s2的引用指向常量池中的“1”对象
System.out.println(s == s2);  //s 和 s2 的引用地址明显不同

  //这行代码在字符串常量池中生成“1” ,并在堆空间中生成s3引用指向的对象(内容为"11")。
  //注意此时常量池中是没有 “11”对象的。
String s3 = new String("1") + new String("1");  
//将 s3中的“11”字符串放入 String 常量池中,
//JDK1.6的做法是直接在常量池中生成一个 "11" 的对象。
//在JDK1.7中,常量池中不需要再存储一份对象了,可以直接存储堆中的引用。
//这份引用直接指向 s3 引用的对象,也就是说s3.intern() ==s3会返回true。
s3.intern();  
String s4 = "11";  //直接去常量池中创建,但是发现已经有这个对象了,此时也就是指向 s3 引用对象的一个引用
System.out.println(s3 == s4);  //1.6 false, 1.7 true

JDK1.6, 与1.7 intern的区别:

String的String Pool是一个固定大小的Hashtable,默认值大小长度是1009,如果放进String Pool的String非常多,就会造成Hash冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用String.intern时性能会大幅下降(因为要一个一个找)。在 jdk6中StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。在jdk7中,StringTable的长度可以通过一个参数指定:-XX:StringTableSize=99991

疑问:
String s = new String(“1”)会在堆和常量池中各创建一个对象;而String s = new String(“1) + new String(“1”)只在堆中创建”11”这个对象,s.intern()会在常量池中引用堆中对象的地址。那为什么String s = new String(“1”)不在堆中创建对象然后直接在常量池里面引用这个地址呢?
答:
事实是String s = new String(“1”)先在常量池里创建一个共享的”1”(如果不存在的话),后在堆上创建对象。

问: 引用块内容关于String str = “abc”的内部工作。

Java内部将此语句转化为以下几个步骤:
(1)先定义一个名为str的对String类的对象引用变量:String str;
(2)在栈中查找有没有存放值为”abc”的地址,如果没有,则开辟一个存放字面值为”abc”的地址,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为”abc”的地址,则查找对象o,并返回o的地址。
(3)将str指向对象o的地址。

里面细节太多, 参照下博客 http://blog.youkuaiyun.com/seu_calvin/article/details/52291082


JAVA内部使用Unicode编码, 而一个char变量占用两个字节,所有char变量可以存储中文


深度克隆

前提是对象实现Serializable接口


    public static <T> T clone(T obj) throws Exception {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);

        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();

        // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
    }

GC

垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:
- 伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
- 幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
- 终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。

与垃圾回收相关的JVM参数:

-Xms / -Xmx — 堆的初始大小 / 堆的最大大小
-Xmn — 堆中年轻代的大小
-XX:-DisableExplicitGC — 让System.gc()不产生任何作用
-XX:+PrintGCDetails — 打印GC的细节
-XX:+PrintGCDateStamps — 打印GC操作的时间戳
-XX:NewSize / XX:MaxNewSize — 设置新生代大小/新生代最大大小
-XX:NewRatio — 可以设置老生代和新生代的比例
-XX:PrintTenuringDistribution — 设置每次新生代GC后输出幸存者乐园中对象年龄的分布
-XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:设置老年代阀值的初始值和最大值
-XX:TargetSurvivorRatio:设置幸存区的目标使用率


获得当前时间

System.currentTimeMillis();// 这个方法返回的是一个long整数,表示GMT 1970年1月1日 00:00:00到现在所经历的毫秒数
Calendar类是一个抽象类。其直接子类是GregorianCalendar

获取

Calendar类一些注意点:
月份是从0开始的, 即如果当前月份是九月, 则calendear.get(Calendar.MONTH) =8;
add()方法, 增加的数目超过额度时自动会向更高一级加1,
roll()方法不会进行进位或者退位运算.

1.getMaximum(int field)和getMinimum(int field)
这两个方法,返回Calendar对象的fields数组中对应数据的最大值和最小值。也就是说,如果我想知道Calendar.DAY_OF_MONTH这个字段能取到的最大值是多少,就可以使用calendar.getMaximum(Calendar.DAY_OF_MONTH)来获取,返回的值是31,因为一个月最多可以有31天。

2.getActualMaximum(int field)和getActualMinimum(int field)
这两个方法名字同上面两个方法相比,多了一个Actual单词,表示返回Calendar对象的fields数组中,在当前日期的环境条件下,对应数据的最大值和最小值。也就是说,如果Calendar对象表示的是2016年的2月,那么使用calendar.getActualMaximum(Calendar.DAY_OF_MONTH)返回的就是29,因为2016年的2月最多只有29天。

Calendar 与Date的关系

  1. 使用getTime()方法, 从Calendar对象中得到Date对象
    Calendar calendar = Calendar.getInstance();
    Date date = calendar.getTime();

  2. 将Date对象赋值给Calendar对象.
    Date date = new Date(3600 * 1000);
    calendar.setTime(date);


其他

日期格式化:
SimpleDateFormat df = new SimpleDateFormat(“yyyy.MM.dd”);

finalize:Object类中定义的方法,Java中允许使用finalize()方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在销毁对象时调用的,通过重写finalize()方法可以整理系统资源或者执行其他清理工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值