Java语法基础
抽象类和接口:
-
抽象类与普通类相似,不同的是,抽象类可以有抽象方法,并且不论有无抽象方法,其自身都不能被实例化。
-
接口与抽象类相似,不同的是,接口不能有构造方法,不能有非抽象方法。
静态方法和实例方法:
- 静态方法属于类,实例方法属于对象
- 静态方法不能被重写,只能重写实例方法
- 重写方法时,可以对方法进行访问权限提升
==与equals方法:
- ==在比较基础类型时,比较的是值,在比较引用类型时,比较的是引用指向的对象的内存地址
- equals方法在比较引用类型时,若无重写,比较的也是对象的内存地址。
拷贝(克隆、clone):
拷贝有两种:
- 浅拷贝
- 深拷贝
当希望复制一个已有对象的内容到另外一个对象时,不能使用复制号"=",会使新的引用指向旧的对象,例子如下:
public class Test {
public static void main(String[] args) {
Person person1 = new Person("xxx");
Person person2 = person1;
System.out.println(person1 == person2);
}
}
class Person {
String name;
public Person(String name) {
this.name = name;
}
}
拷贝必须使用Object类提供的clone方法:
- 被克隆类需实现Clonable接口
- 被克隆类覆盖clone方法并把访问权限提升为public
当一个类重写了clone方法,这个类的实例是可以进行浅拷贝的,即:clone时,创建一个新对象,并将实例的域全部使用赋值号"="赋值到新对象,这样造成的结果是,如果实例中含有其它实例,子实例将不会被拷贝一份,所以称为浅拷贝。例子如下:
- Person的实例拥有域name和域address,其中address是对象类型
- 在clone时,address将不会拷贝一份,两个对象中的address指向同一个对象
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("xxx", new Address("北京"));
Person person2 = (Person) person1.clone();
System.out.println(person1 == person2);
System.out.println(person1.address == person2.address);
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Address {
String addressName;
public Address(String addressName) {
this.addressName = addressName;
}
}
想对一个类进行深拷贝,在拷贝时,必须显式地拷贝子对象,如下:
- Address类也覆盖clone方法
- 在上述main方法中增加一句:
person2.address = (Address) person1.address.clone(); // 显式拷贝子对象
完整代码如下:
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Person person1 = new Person("xxx", new Address("北京"));
Person person2 = (Person) person1.clone();
person2.address = (Address) person1.address.clone(); // 显式拷贝子对象
System.out.println(person1 == person2);
System.out.println(person1.address == person2.address);
}
}
class Person implements Cloneable {
String name;
Address address;
Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Address implements Cloneable{ //子类覆盖clone方法
String addressName;
public Address(String addressName) {
this.addressName = addressName;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
&和&&的区别:
&和&&都会先计算左边的表达式,如果左边表达式为false:
- &还会继续计算右边的表达式
- &&不会继续计算右边的表达式
&除逻辑运算外还可以进行位运算。
Java中只有值传递:
public class Test {
public static void main(String[] args) {
int a = 6;
method(a);
System.out.println(a);
}
static void method(int a) {
a = 5;
}
}
上述代码中,如果Java是引用传递,则a会在method中被修改。
若将a改为对象,a确实会被修改:
public class Test {
int a;
public static void main(String[] args) {
Test test = new Test();
test.a = 6;
method(test);
System.out.println(test.a);
}
static void method(Test test) {
test.a = 5;
}
}
但这只能说明main方法中的变量test将自身指向的对象地址给了局部变量test。
以下也说明了Java是值传递:
public class Test {
int a;
public static void main(String[] args) {
Test test = new Test();
test.a = 6;
method(test);
System.out.println(test.a);
}
static void method(Test test) {
test = null;
}
}
可以看到,main中的变量test没有指向null,这是值传递的特征。