目录
一、注解
内置注解:JAVA中已经定义好的注解。
元注解:修饰注解的注解。
自定义注解。
二、克隆
JAVA中对clone的实现?
浅克隆
深克隆
那么该如何做到深克隆呢?
三、常用设计模式
1、创建型模式
单例模式
工厂模式
工厂方法模式
抽象工厂模式
原型模式
一、注解
java中的注解也称标注,可以用来对类、方法、属性、参数、包等进行标注。然后让编译器或运行时其他类进行解析。完成某个功能注解也可以编译到字节码文件中。
内置注解:JAVA中已经定义好的注解。
@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。@SuppressWarnings - 指示编译器去忽略注解中声明的警告。@FunctionalInterface 用于指示被修饰的接口是函数式接口。
元注解:修饰注解的注解。
@Retention - 标识这个注解怎么保存,是只在代码中,还是编入 class 文件中,或者是在运行时可以通过反射访问。@Documented - 标记这些注解是否包含在用户文档中。@Target - 标记这个注解应该是哪种 Java 成员。@Inherited - 标记这个注解是继承于哪个注解类(默认注解并没有继承于任何子类)@Repeatable - 标识某注解可以在同一个声明上使用多次。
自定义注解。
二、克隆
克隆分为浅克隆、深克隆。
JAVA中对clone的实现?
①实现Cloneable接口
②重写clone方法(Object类中的方法)
浅克隆
克隆一个对象时,如果对象中有关联关系(has-a,把一个类当作另一个类的属性),只将关联对象的地址复制过来(只拿地址)
举例:
public class CloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Student s1=new Student();
Address address=new Address();
address.setAddress("江苏");
s1.setName("Mike");
s1.setAge(20);
s1.setAddress(address);
Student s2=s1.clone();
s2.setAge(21);
s2.setName("Amy");
address.setAddress("陕西");
s2.setAddress(address);
System.out.println(s1);
System.out.println(s2);
}
}
public class Student implements Cloneable{
int age;
String name;
Address address;
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", address=" + address.address +
'}';
}
}
public class Address {
String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
运行结果
这是一个浅克隆的例子, 主函数中定义了一个叫Mike的Student对象实例,Student类中有基本类型age和name,还有引用类型Address。我们在主函数中使用了Object类中的方法clone() (重写了该方法)
@Override
protected Student clone() throws CloneNotSupportedException {
return (Student) super.clone();
}
从运行结果发现基本数据类型修改不影响被克隆的对象,但是关联对象数据被修改,克隆的和被克隆的对象都被修改了。可以证明 浅克隆的定义:克隆一个对象时,如果对象中有关联关系(has-a,把一个类当作另一个类的属性),只将关联对象的地址复制过来(只拿地址)
所以浅克隆支持引用类型成员变量的复制
并且我们发现,克隆的对象和被克隆的对象的地址不同,即使用clone()方法 会创建一个新对象,这里区别于JAVA中的引用
深克隆
克隆一个对象时,如果对象中有关联关系,将关联对象一同克隆(创建一个新的关联对象)
那么该如何做到深克隆呢?
1、连同关联对象一同克隆,逐级克隆(层级过多会比较麻烦)
public class CloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Student s1=new Student();
Address address=new Address();
address.setAddress("江苏");
s1.setName("Mike");
s1.setAge(20);
s1.setAddress(address);
Student s2=s1.clone();
s2.setAge(21);
s2.setName("Amy");
address.setAddress("陕西");
System.out.println(s1);//Mike 20 陕西
System.out.println(s2);//Amy 21 江苏
}
}
public class Student implements Cloneable{
int age;
String name;
Address address;
@Override
protected Student clone() throws CloneNotSupportedException {
Student s=(Student) super.clone();
Address address=(Address)s.getAddress().clone();
s.setAddress(address);
return s;
}
}
public class Address implements Cloneable{
String address;
@Override
protected Address clone() throws CloneNotSupportedException {
return (Address) super.clone();
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
在Student类中再使用clone()方法克隆Address对象,并且在Address类中重写clone()方法。
运行结果
通过结果发现,改变了关联对象地址,克隆对象的地址并未改变,说明深克隆不支持引用类型成员变量的复制。
2、序列化(对象的输入输出流)
三、常用设计模式
1、创建型模式
用于描述“怎样创建对象”,它的主要特点是“将对象的创建与使 用分离”。提供了单例、原型、工厂方法、抽象工厂、建造者 5 种创建型模式。
单例模式
在有些系统中,为了节省内存资源、保证数据内容的一致性,对某些类要求 只能创建一个实例,这就是所谓的单例模式. 例如,Windows 中只能打开一个 任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费, 或出现各个窗口显示内容的不一致等错误。单例模式有 3 个特点: 1. 单例类只有一个实例对象; 2. 该单例对象必须由单例类自行创建; 3. 单例类对外提供一个访问该单例的全局访问点;
工厂模式
1、简单工厂:有一个工厂类负责生产某一类产品,同一类产品具备同一个抽象父类(抽象类/接口)。将创建对象与使用对象分离(Spring框架的设计思想)。简单工厂违背了开闭原则,添加一个产品就需要修改代码。子类过多,会导致工厂类庞大
以手机工厂为例:
手机接口:
public interface Phone {
public void run();
}
手机工厂接口:
public interface PhoneFactory {
void createPhone();
}
有两种品牌的手机:HUAWEI和IPhone
手机工厂,重写创建手机方法
public class PhoneFactory {
static Phone createPhone(String name) {
if (name.equals("HUAWEI")) {
return (Phone) new HUAWEI();
}else if(name.equals("IPhone")){
return (Phone) new IPhone();
}else {
return null;
}
}
}
华为手机运行
public class HUAWEI implements Phone{
@Override
public void run() {
System.out.println("使用华为手机");
}
}
iPhone手机运行
public class IPhone implements Phone{
@Override
public void run() {
System.out.println("使用苹果手机");
}
}
主函数
public class Solution {
public static void main(String[] args) {
PhoneFactory huaweiFactory=new HUAWEIFactory();
Phone huaweiPhone=new HUAWEI();
huaweiPhone.run();
PhoneFactory iphoneFactory=new IPhoneFactory();
Phone iphonePhone=new IPhone();
iphonePhone.run();
}
}
运行结果:
工厂方法模式
对工厂进行抽象,一个抽象的产品对应一个抽象的工厂。一个具体的产品对应一个具体的工厂,一个具体的工厂负责生产一个具体的产品,需要扩展新产品时,只需要添加新的具体的产品类,和新的生产该产品的工厂类即可。这样就不需要修改原来的工厂,符合开闭原则。
手机接口:
public interface Phone {
public void run();
}
手机工厂接口:
public interface PhoneFactory {
void createPhone();
}
有两种品牌的手机:HUAWEI和IPhone
HUAWEI手机工厂
public class HUAWEIFactory implements PhoneFactory{
@Override
public void createPhone() {
new HUAWEI();
}
}
iPhone手机工厂
public class IPhoneFactory implements PhoneFactory{
@Override
public void createPhone() {
new IPhone();
}
}
华为手机运行
public class HUAWEI implements Phone{
@Override
public void run() {
System.out.println("使用华为手机");
}
}
iPhone手机运行
public class IPhone implements Phone{
@Override
public void run() {
System.out.println("使用苹果手机");
}
}
主函数
public class Solution {
public static void main(String[] args) {
PhoneFactory huaweiFactory=new HUAWEIFactory();
Phone huaweiPhone=new HUAWEI();
huaweiPhone.run();
PhoneFactory iphoneFactory=new IPhoneFactory();
Phone iphonePhone=new IPhone();
iphonePhone.run();
}
}
运行结果:
抽象工厂模式
抽象工厂时生产一系列产品(某公司的产品华为手机,华为汽车),在抽象工厂中定义生产不同的产品,具体工厂负责生产一个公司的一系列产品
定义一个抽象工厂
public interface AbstractFactory {
Car getCar();
Phone getPhone();
}
定义 汽车接口,手机接口
public interface Phone {
void call();
}
public interface Car {
void run();
}
定义产品工厂
public class RedmiFactory implements AbstractFactory{
@Override
public Car getCar() {
return new RedmiCar();
}
@Override
public Phone getPhone() {
return new RedmiPhone();
}
}
产品信息
public class RedmiPhone implements Phone{
@Override
public void call() {
System.out.println("红米手机,年轻人的选择");
}
}
public class RedmiCar implements Car{
@Override
public void run() {
System.out.println("米家汽车,安心可靠");
}
}
主函数
public class Solution {
public static void main(String[] args) {
AbstractFactory redmiFactory=new RedmiFactory();
Car redmiCar=redmiFactory.getCar();
Phone redmiPhone= redmiFactory.getPhone();
redmiCar.run();
redmiPhone.call();
}
}
运行结果
原型模式
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能(new一个对象非常昂贵)。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。