l
构造函数
构造函数名必须与类名相同,首字母也要大写。构造函数里面一般是进行初始化操作的。
当一个类中没有任何自己定义的构造函数时,系统自动生成默认的无参数构造函数。如果已有自己定义过的构造函数,则不会自动生成默认构造函数了。
l
关于方法重载的理解
构造函数和方法都可以进行重载,重载指的是方法名相同,参数列表不同。参数列表不同包括:参数类型不同,参数数目不同,参数顺序不同。(
参数顺序不同一般不建议使用,会使代码混乱)
使用重载的情形:当有明显相同的概念时就可以使用重载。
涉及基本类型变量做参数的方法重载:
当形参类型比实参大时,进行自动扩展转换。(
对于
char
类型是跳过short
直接往上转换为int
类型的,当有多个重载方法时,而且同时有short
和int
做参数的方法)
当形参类型比实参小时,必须进行强制类型转换(窄化转换,可能损失精度)。
对于类类型,也是自动向上转型,而强制向下转型。
不可以用返回值和方法体来区分重载的方法,编译时会抛错!
l
this
关键字的用法
this有两种用法:(1)方法内部使用 (2)构造函数内部使用
(1):在方法内部使用时,this代表了调用该方法的当前对象的引用。一般在该方法内调用其他方法时不用写明this,会自动完成。只有需要返回当前对象的引用时用到this,如return this;还有就是当方法内有跟类中成员变量同名的变量(也包括形参)时,要访问类中成员变量就要在其前面加上this。
(2):当构造函数内要调用同一个类中另外的构造函数,以节省重复代码时,可以用this来实现,此时this代表对某个构造函数的调用,含义与(1)中不同。
另外,在构造函数内部也可以像方法中一样使用
this
关键字。如:
public class A{
public A(){}
public A(int i){
this();
}
}
注意:this只能调用一次构造函数,不调用多个构造函数。并且this必须写在该构造函数内的第一行。this(param),参数param决定了调用哪个构造函数。
构造函数只能在构造函数中被调用,不允许在方法中被调用
l
关于static
的理解
static的方法中不能调用非静态的成员变量或者方法,也就不能使用this了。反过来是可以的。static方法一般用类名来直接访问,这样代码也好读懂。
另外
java
中消除了前向引用
l
对垃圾回收机制的理解
(1) 垃圾回收何时启动
一般情况下,要等到jvm虚拟机觉得受到了内存濒临耗尽的危险时,才会启动垃圾回收器。因为垃圾回收的过程比较耗费时间(有确定垃圾和回收两大部分),所以jvm虚拟机是不会随便浪费时间来进行垃圾回收,以恢复内存空间。并且如果程序结束前都没有执行垃圾回收,那么程序结束后,所有内存空间都会还给操作系统的。
但是通过调用System.gc()
方法可以强制执行垃圾回收
(2) 回收哪些对象,如何判断的
回收的是那些不再被使用的对象,即没有指向他们的引用变量了。判断时机是,以开始垃圾回收的那一刻(比如执行System.gc()方法时)为时间点,如果此时有对象没有任何引用指向它,那么就释放它所占用的内存空间。
(3) 关于finalize()的理解
当系统准备释放某个垃圾对象所占用的内存空间时,会对它调用finalize()方法。因为垃圾回收只释放那些通过new方式创建的对象所占用的空间,所以可以在fianlize()里做些别的清理工作,因为也可能存在某个对象里调用了不通过new方式创建的对象,从而占据了一段特殊的内存空间。
调用完finalize()方法后,就开始释放内存空间。
(4) 如何找到垃圾,并实施回收的
找到垃圾有两种方式:
(1)引用计数法
即为每个对象都捆绑一个计数器,每当有一个新的引用指向该对象,它的计数器就加1,如果其计数为0,则是垃圾。引用计数技术很少被使用,只是用来解释用的。
(2)顺藤摸瓜法
因为每个对象都是通过引用来操纵的,而且引用变量都是存放在堆栈中,所以可以在堆栈和静态存储区中遍历所有的引用来访问到活着的对象,并对其进行标记(
引用变量在超出作用域后会自动从堆栈中消失,所以不担心其释放问题)。
回收有很多的算法,在这里只简单列举自己了解的两种
(1)“标记-清扫”
即标记出那些活着的对象,然后清除垃圾,这样会产生堆的不连续存储空间
(2)“停止-复制”
先将所有活着的对象复制到一个新堆中,然后清除原堆内的对象。这样新堆中的对象空间是连续存放的。
回收方式也有“同步”和“异步”两种
(1)PC机上一般用同步,即暂停所有处理的程序,去执行回收,所以有时候会感觉编程时机器很慢。
(2)异步方式,是先暂停处理,然后标记,在对系统分区,在分区里执行回收
(5) 垃圾回收机制中应该要注意的三大点
l 对象可能不被垃圾回收
l 垃圾回收不同于析构函数
l 垃圾回收只与内存有关
(6) 与C/C++比较
C中没有垃圾回收的,都是程序员自己手动释放空间。
C++中有析构函数来完成垃圾回收,但是也是要通过程序员手动调用来实现的。
l
成员初始化
类成员:如果是基本类型变量系统自动初始化为默认值(char类型,默认值是0即‘空白字符’),引用变量则系统自动指向null
局部变量:基本类型和引用变量都是初始化为任意值,而必须自己手动初始化了之后,才可以在以后访问它们。
否则编译时会抛错(建议声明的时候就初始化)
l 初始化的顺序
分两种情况讨论:
局部变量的修饰符只能是final
或者空,不可以是static
的
(一) 第一次通过类名访问类的静态成员
1 加载类,通过classpath
2 为静态成员分配内存空间
3 对所有静态成员进行默认初始化
4 执行类中定义的静态成员初始化语句,如果有的话
因为这种情况没有创建对象,所以没有后续操作。
(二) 第一次创建该类的对象
1 加载类,通过classpath
2 为静态成员分配内存空间
3 对所有静态成员进行默认初始化
4 执行类中定义的静态成员初始化语句,如果有的话
5 在堆中为对象分配空间
6 执行非静态成员的默认初始化
7 执行类中定义的非静态成员初始化语句,如果有的话
8 执行构造函数
静态成员只初始化一次!!!
l
关于初始化语句块
有static 和 非static 两种,如:
static {}
{}
这两者都是替代了单行的成员变量初始化语句,并且还可以在里面加一些自己想额外执行的语句。
后者在匿名类中比较常用,其他情况下很少用到这两者。
l
前向引用和后向引用
前向引用:指后面的引用前面的,这个肯定没问题。
后向引用:指前面的引用后面的,java中只支持方法的后向引用,不支持变量的后向引用
l
Java
中的数组
Java中的数组会自动执行越界检查,虽然运行开销大,但是安全性高,所以是值得的。
C/C++中是不会执行越界检查,允许下标越界访问,带来了安全问题。
int[] a;//也可以使用int a[]但是,java中推荐前者。
int[5] a;//
这样做会抛出编译时异常,java
不允许在声明时指定数组大小
//上面语句声明了一个指向数组的引用,并未创建数组,没有开始分配空间呢。
int[] a1 = a;//引用赋值后,a1也指向了a所指向的数组。a1,a可以访问的是同一个数组
(1)
int[] b = new int[5];
for(int i = 0;i<5;i++){
b[i] = val;
}//这是第一种创建数组的方式
(2) int[] b = {val1,val2,val3}//这是第二种创建数组的方式
(3) int[] b = new int[]{val1,val2,val3}//这是第三种创建数组的方式,
两个方括号内都不能指定数组大小
对象数组跟基本类型数组是一样的方式
在第(1
)种创建方式中,如果没有后面的for
语句,则数组会默认初始化。基本类型变量为默认值,引用则指向null
l
多维数组
创建方式可以同一维数组一样
第(2)种方式,可以这么创建:
int[][] a = {{1,2}{3,4}{5,6}}
此时a.length
为第一维长度3
a[0].length = a[1].length=a[2].length =
第二维长度2
l
Object
类中的toString()
方法返回的是“类名+
对象的地址”