对象的内存解析:(部分内容及图片转自尚硅谷课程,版权归尚硅谷所有)
注意:1.不能在方法内部定义方法。2.方法中的变量都是局部变量,存在栈空间中。3.对象的非static属性是加载在堆空间中。
4.方法区中有:类的加载信息、常量池、静态域。
对象的内存(易错的地方:)
Teacher[] t = new Teacher[3];
System.out.println(t);//输出一个地址
System.out.println(t[0]);//输出null
t[0].age = 50;//会报错因为没有为t[0]分配内存
t[1] = new Teacher();
System.out.println(t[1]);//会输出对象t[1]的地址
t[1].age = 50;//不会报错,因为已经为t[1]分配了内存
class Teacher{
int age;
}
Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响:
1. 如果形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
2. 如果形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参
this关键字:
1.可以使用this.属性或this.方法调用当前对象的属性或方法;
2.可以使用this(形参列表)的形式在当前构造器中调用其他构造器;
3.当使用this在一个构造器中调用其他构造器时,“this(形参列表)”必须声明在类的构造器的首行,因此,在类的构造器中,最多只能声明一个this(形参列表)。
方法重写(override):
1. 重写的方法与被重写的方法的方法名和参数列表相同;
2. 重写的方法的权限修饰符不小于被重写的方法的权限修饰符。注:父类中private修饰的方法不能被重写。
3. 返回值类型:
① 父类中被重写的方法是void,子类中重写的方法只能是void;
② 被重写的方法的返回值是基本数据类型(比如double),则子类中重写的方法的返回值类型必须是相同的类型(只能是double,对应前一个括号);
③ 父类中被重写的方法的返回值是A类型,子类中重写的方法的返回值应当是A类型或A的子类;
4. 子类中重写的方法抛出的异常不大于父类被重写的方法抛出的异常。
多态性:
Person p1 = new Man();
其中:person是父类,man是子类
对象的多态性就是父类的引用指向子类的对象(或子类的对象赋给赋给父类的引用)
在编译期只能调用父类声明的方法,但在运行期,实际执行的是子类重写父类的方法;即:编译看左边,运行看右边。
但是不能调用子类特有的方法。如果要调用子类特有的方法,使用类型强转。
Person p = new Man();
Man m = (Man)p; //类型强转,向下转型
instanceof关键字:
为了避免强转错误,引入instanceof关键字:对象名 instanceof 类名,返回true或false
Person m = new Man();
if(m instanceof Man){
Man m2 = (Man) m;
}
多态性不适用于属性(可以理解为属性不能被重写)。
*****************************************分隔符*******************************************************************
面试题:“==” 和equals()的区别:
一. ==:是运算符;使用方法如下:
1. 可以使用在基本数据类型和引用数据类型中,但是int、double、char等基本类型不能和Boolean类型比较;
//基本类型的比较
int i = 10;
double j = 10.0;
char k = 10;
sysout(i == k);//true
sysout(i ==j); //true
2. 如果比较的是基本数据类型变量,比较两个变量保存的数据是否相同。(类型不一定非要相同,int和double之间也可以比)
3. 如果比较的是引用类型的变量,比较两个对象存放的地址值是否相同,即两个引用是否指向同一个对象实体,例如:
//引用类型的比较
main{
student s1 = new student(20);
student s2 = new student(20);
sysout(s1 == s2); //false
sysout(s1.age == s2.age);//true
String st1 = new String("java");
String st2 = new String("java");
sysout(st1 == st2); //false
}
class student{
int age;
}
public student(int age){
this.age = age;}
二. 1. equals()是方法,只能适用于引用类型
2. object类中定义的equals()和 == 的作用是相同的: 比较两个对象的地址值是否相同,即两个引用是否指向同一对象
3. 像string、data、file等类中都重写了object中的equals()方法;重写以后比较的不是地址值,而是两个对象的“实际内容”是否相同
main{
Customer c1 = new Customer("tom", 21);
Customer c2 = new Customer("tom", 21);
String s1 = new String("java");
String s2 = new String("java");
System.out.println(c1.equals(c2));//false
System.out.println(s1.equals(s2));//true
}
static关键字:
一. 使用范围:
在Java类中,可用static修饰属性、方法、代码块、内部类
被修饰后的成员具备以下特点:
1. 随着类的加载而加载
2. 优先于对象存在
3. 修饰的成员,被所有对象所共享
4. 访问权限允许时,可不创建对象,直接被类调用。
二. static修饰属性(静态属性、类属性、类变量)的其他说明:
1. 可通过“类名.静态变量的方式”进行调用;
2. 静态变量的加载要早于对象的创建;
3. 由于类只会加载一次,则静态变量在内存中也只会存在一份:存在方法区的静态域中。
三. static修饰方法(静态方法)的其他说明:
1. 可通过“类名.静态变量的方式”进行调用;
2. 静态方法中,只能调用静态属性或静态方法;非静态方法中,既可以调用静态方法或静态属性,也可以调用非静态方法或非晶态属性;
3. 静态方法中,不能使用this或super关键字。
final可以修饰类、方法、变量(包括属性和形参)
代码块的使用:
1 代码块的作用:用来初始化类、对象
2 代码块只能使用static修饰或不加任何修饰;即静态代码块、非静态代码块
3 静态代码块:① 内部可以有输出语句;随着类的加载而自动执行,只执行一次(因为类只加载一次);
② 静态代码块可以有多个,按照顺序依次执行,静态的代码块优先于非静态代码块执行,
③ 一般情况下,不写多个静 态代码块;静态代码块内,只能调用静态的属性和方法
4 非静态代码块:① 内部可以有输出语句;随着对象的创建而执行,每创建一个对象,就执行一次;“可以在创建对象时,对属性进行初始化”,
② 一般情况下,不写多个非静态代码块;非静态代码块内,可以调用静态和非静态的属性和方法。
单例设计模式:饿汉式:
饿汉式好处:是线程安全的
坏处:对象加载时间过长
public static void main(String[] args) {
Bank bank1 = Bank.getInstance();
Bank bank2 = Bank.getInstance();
System.out.println(bank1 == bank2);
}
}
class Bank{
//1 私有化构造器
private Bank() {
}
//2 内部创建类的对象
private static Bank instance = new Bank(); //此对象也必须是静态的
//3 提供公共的静态方法,返回类的对象
public static Bank getInstance() {
return instance;
}
}
懒汉式:
懒汉式好处:延迟对象的创建
坏处:线程不安全
public static void main(String[] args) {
Order o1 = Order.getInstance();
}
}
class Order{
//1 创建私有的构造器
private Order(){
}
//2 声明当前类的静态对象
private static Order instance = null;
//3 声明公共的静态方法,返回当前对象
public static Order getInstance() {
if(instance == null) {
instance = new Order();
}
return instance;
}
}
abatract关键字:可以修饰类、方法
修饰类:此类不能实例化
修饰方法:抽象方法,抽象方法只有方法的声明,没有方法体,不可被调用;包含抽象方法的类一定是抽象类 ,反之,抽象类中可以没有抽象方法。子类重写了父类中所有的抽象方法后,此子类才可实例化
abstract不能用来修饰私有方法、静态方法、final的类和方法
接口:
接口中不能定义构造器 意味着接口不能实例化
类可以实现接口:如果此类重写了接口中所有的抽象方法,则此类可以实例化
如果此类没有重写接口中所有的抽象方法,则此类仍为一个抽象类
类可以实现多个接口
接口与接口之间可以多继承
接口的具体使用,体现多态性
接口是一种规范
jdk7.0及以前:只能定义全局常量和抽象方法
全局常量:public static final 可以省略
抽象方法:public abstract
jdk8.0: 还可以定义静态方法(只能通过接口名调用)、默认方法(要使用default修饰)