接口
/*
接口也是一种数据类型。
父类可以表示一系列继承自父类的子类的类型。
接口和父类一样,也可以使用接口表示一系列实现了接口的类的类型。
继承通常表示is - a的关系,xxx是yyy的一种。
苹果是水果的一种。
接口通常表示hava - a的关系,xxx有(会)yyy。
鼠标有Usb接口可以链接电脑。
interface 接口。
只能定义一种类型的属性和方法。
属性:只能定义public static final的常量。
方法:只能定义public abstract类型的方法。
只能定义常量,大部分情况下都是只有抽象方法,常量并不常用。
通常省略public abstract ,系统会自动帮我们补全。
implements 实现接口的关键字。
接口和抽象类一样。
如果实现了接口,必须实现接口中所有的抽象方法。除非设置为抽象类。
*/
public interface Usb {
/**
* usb 设备的名字
* @return
*/
String usbDeviceName();
}
public class UDisk implements Usb {
@Override
public String usbDeviceName() {
return "U 盘";
}
}
public class Mouse {
public String usbDeviceName() {
return "鼠标";
}
}
public class Computer {
/**
* 只有遵守规范,什么都可以链接
* @param usb
*/
public void connectUsb(Usb usb) {
String name = usb.usbDeviceName();
System.out.println(name + "...连接上电脑了");
}
}
public class Demo {
public static void main(String[] args) {
int s [] = new int [10];
Computer computer = new Computer();
UDisk uDisk = new UDisk();
Mouse mouse = new Mouse();
computer.connectUsb(uDisk);
// computer.connectUsb(mouse);
// 接口不能创建对象,只能使用实现了接口的类创建对象
// 除非使用匿名类,创建一个实现了接口的没有名字的类的对象
Usb usb = new Usb() {
@Override
public String usbDeviceName() {
// TODO Auto-generated method stub
return null;
}
};
// Usb 是 u2 的编译时类型
// UDisk 是 u2 的运行时类型
Usb u2 = new UDisk();
}
}
Java中堆与栈
public class Pet {
public String name;
}
public class People {
public static String COUNTRY = "中国";
public String name = "张三";
public int age = 20;
public Pet pet;
public People() {
this.name = "李四";
this.age = 30;
}
}
public class Demo {
public static void main(String[] args) {
People p1 = new People();
// 1. 把 People.class 加载到方法区
// 2. 在栈上开辟空间存储 p1
// 3. 在堆开辟空间存储 People 对象
// 4. 给属性 name 和 age 赋予默认值,null 和 0
// 5. 给属性 name 和 age 赋予值,张三,20
// 6. 调用构造方法,给属性 name 和 age 赋予值,李四,30
// 7. 把堆上地址赋值给栈上的 p1
p1.age = 50;
// 1. 根据 p1 保存的地址,找到堆上的对象存储空间
// 2. 找到 age 对应的存储空间
// 3. 修改 age 的值为 50
int age = 30;
// 1. 栈上开辟空间存储 age
// 2. 把 30 存在 age 位置
People p2 = new People(); // new 开辟内存,创建新对象
// 2-7 的流程走一遍
p2.age = 80;
People p3 = p1;
// 1. 栈上开辟空间存储 p3
// 2. 把 p1 保存的地址赋予 p3
// p1 和 p3 就指向堆上的同一块内存地址
p3.name = "蜘蛛侠";
System.out.println(p1.name);
p3.COUNTRY = "美国";
System.out.println(p2.COUNTRY);
Pet pet = new Pet();
// 1-7 的流程,创建对象得到堆上的地址 0x010 赋给 pet
// 只有 new 的时候才会创建新的对象,赋值是传递地址
p1.pet = pet; // 把 0x010 存到 p1.pet 中
p1.pet.name = "旺财";// 修改的是 0x010 中的 name
System.out.println(pet.name);// 输出的也是 0x010 中的名字
method1(age); // 基本类型传递的是值,方法内部改变不了 age 的值
System.out.println(age);
method2(p1); // 引用类型传递的是地址,方法内部可以改变对象的属性的值
System.out.println(p1.age);
method3(p1);
System.out.println(p1.age);
// 栈:空间小,读写速度快
// 堆:空间大,读写速度相对较慢
// 基本类型分配在 栈 上,保存的是数据的值
// 引用类型分配在 堆 上,会在栈上保存一个地址的引用,称为指针
// final 类型定义的变量值不能修改
final int a = 10;
// a = 100;
final People p7 = new People();
p7.age = 100;// 为什么可以?
// p7 = p1;
// p7 = new People();
}
public static void method1(int age) {
//
age = 50;
}
public static void method2(People p1) {
p1.age = 50;
}
public static void method3(People p1) {
// People p1 = p1;
// 创建新变量 p1,值为方法调用的时候传入的 p1 的值 0x001
p1 = new People(); // p1 = 0x009,产生新对象,不在影响原来的对象
p1.age = 70; // 修改 0x009 的值
}
}