Java 基础知识(不断迭代版)
我也刚入门,请批判性看待
开局Hello World,保存的文件名应该为 MyHelloWorld .java,如下所见类名为MyHelloWorld ,main为方法名,且main为主方法入口。
public class MyHelloWorld {
public static void main(String []args) {
//这里输出打印
System.out.println("Hello World");
}
}
1·基本语法注意点
1. 源文件名和类名相同:
当保存文件的时候,你应该使用类名作为文件名保存(切记Java是大小写敏感的),文件名的后缀为.java。(如果文件名和类名不相同则会导致编译错误)。例如以上Hello World例子,则需要保存为 MyHelloWorld.java
2. 大小写敏感:
Java是大小写敏感的,这就意味着标识符Hello与hello是不同的,重要的事情说三遍。
Java是大小写敏感的。
Java是大小写敏感的。
Java是大小写敏感的。
3. 类名首字母大写:
对于所有的类来说,类名的首字母应该大写,及遵循帕斯卡命名法。例如上述例子的:MyHelloWorld 类名
单字之间不以空格断开或连接号(-)、底线(_)连结,第一个单字首字母采用大写字母;后续单字的首字母亦用大写字母,例如:FirstName、LastName。每一个单字的首字母都采用大写字母的命名格式,被称为"Pascal命名法",源自于Pascal语言的命名惯例,也有人称之为"大驼峰式命名法"(Upper Camel Case),为驼峰式大小写的子集。
4·方法名小写开头
所有的方法名都应该以小写字母开头,采用驼峰式命名法。即如果方法名含有若干单词,则后面的每个单词首字母大写。
5·主方法入口:
所有的Java 程序由public static void main(String args[])方法开始执行。
2·修饰符
修饰符分2种:
1·访问控制修饰符 : default, public , protected, private
2·非访问控制修饰符 : final, abstract, static, synchronized
3· JVM(虚拟机内存划分)
JVM(虚拟机)内存的划分为:
1·寄存器
2·本地方法区
3·方法区
4·栈内存(stack)
栈内存首先是一片内存区域,存储的都是局部变量, 凡是定义在方法中的都是局部变量(方法外的是全局变量), for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量, 变量有自己的作用域,一旦离开作用域,变量就会被释放。 栈内存的更新速度很快,因为局部变量的生命周期都很短。
5·堆内存(heap)
存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中, 堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性), 如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的, 但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。 堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。
4·基本数据类型
Java的两大数据类型:
1·内置数据类型
2·引用数据类型
引用类型是一种对象类型,它的值是指向内存空间的引用,就是地址!!!
分为以下3种,且默认值均为null:
1·数组
2·类
3·接口
而包装类型作为引用类型中的一种,是java为每种基本类型都提供了对应的封装类型(ps:包装类型),分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean。
包装类型缓存处理
Byte、Short、Integer、Long、Char这几个装箱类的valueOf()方法都会做缓存, 而Float、Double则不会,原因也很简单, 因为byte、Short、integer、long、char在某个范围内的整数个数是有限的,但是float、double这两个浮点数却不是。
3·内置数据类型和包装类型的要点
1·内存分配
内置数据类型的变量是存储在stack(栈)内存中,变量是有值的;
引用数据类型的变量也是存储在stack(栈)内存中,默认该变量为Null,当该变量被new出来后,具体内容保存在 heap(堆)内存中,而该变量存储的是实际对象在heap(堆)内存中的地址。
2·自动装箱、拆箱
jdk 1.5后引用了自动装箱和拆箱,用于内置数据类型和包装类型的转换,例如 int 和 Integer 之间的转换。
1·自动装箱
java自动将原始类型转化为引用类型的过程,自动装箱时编译器会调用valueOf方法,将原始类型转化为对象类型。
注意: Byte、Short、Integer、Long、Char这几个装箱类的valueOf()方法都会做缓存,且缓存范围均为:-128到127,超过之后便会new 一个对象。[ps:这里可以查看第3点equals和== 的区别]
例如通过查看Integer.valueOf的源码,我们可以看到如下代码:
/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
再查看IntegerCache 的源码:
/**
* Cache to support the object identity semantics of autoboxing for values between
* -128 and 127 (inclusive) as required by JLS.
*
* The cache is initialized on first usage. The size of the cache
* may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
* During VM initialization, java.lang.Integer.IntegerCache.high property
* may be set and saved in the private system properties in the
* sun.misc.VM class.
*/
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
private IntegerCache() {}
}
2·自动拆箱
java自动将引用类型转化为原始类型的过程,自动拆箱时编译器会调用intValue(),doubleValue()这类的方法将对象转换成原始类型值。
3·自动拆装箱的问题
3·1影响程序性能,因为装箱会隐式地创建对象,当频率过高时会额外创建多余的对象,增加GC的压力,影响程序的性能,尤其是在循环中处理时。
3·2如上述所说,引用类型是一种对象类型,它的值是指向内存空间的引用,就是地址,其默认值为null。所以包装类型作为引用类型中的一种,当其值为null时转换为内置数据类型,则会报空指针异常(即:抛异常为NPE,是NullPointException的缩写)
3·equals和== 的区别
equals是判断两个变量或者实例指向同一个内存空间的值是不是相同, 而==是判断两个变量或者实例是不是指向同一个内存空间。
import java.util.List;
import java.util.LinkedList;
public class Aaaa {
public static void main(final String[] args) {
IntegerTest();
}
static void IntegerTest() {
try {
final Integer a = (int) Byte.MIN_VALUE - 1;
final Integer b = (int) Byte.MIN_VALUE - 1;
check(a, b);
final Integer c = (int) Byte.MAX_VALUE;
final Integer d = (int) Byte.MAX_VALUE;
check(c, d);
final Integer e = 0xff;
final Integer f = 0xff;
check(e, f);
} catch (final Exception e) {
System.out.println(e.toString());
}
}
static void check(final Integer num1, final Integer num2) {
System.out.println(String.format("%d-->%d,== :%b", num1, num2, num1 == num2));
System.out.println(String.format("%d-->%d,equals :%b", num1, num2, num1.equals(num2)));
}
}
输出结果为:
-129–>-129,== :false
-129–>-129,equals :true
127–>127,== :true
127–>127,equals :true
255–>255,== :false
255–>255,equals :true