笔记:java面向对象编程

值传递与引用传递

  1. 值传递并未在以下代码中产生效果
//值传递
public class Demo01 {
    public static void main(String[] args) {
        int a = 0;
        System.out.println(a);

        Demo01.change(a);
        System.out.println(a);
    }
    public static void change(int a){
        a = 10;
    }

}
  1. 引用传递 形参为对象,本质为值传递
//引用传递
public class Demo02 {
    public static void main(String[] args) {
        Student student = new Student();
        System.out.println(student.name);

        Demo02.change(student);
        System.out.println(student.name);
    }
    public static void change(Student student){
        student.name = "lob";
    }
}

class Student {
    String name;
}

有参构造与无参构造

使用alt + insert 快捷键组合生成

super

  1. super调用父类的构造方法,必须在构造方法的第一个
  2. super必须只能出现在子类的方法或者构造方法中
  3. super 和this不能同时调用构造方法

重写:需要有继承关系,子类重写父亲的方法(@Override)

  1. 方法名必须相同

  2. 参数列表必须相同

  3. 修饰符:范围可以扩大但不能缩小: public>protected>default>private

  4. 抛出的异常范围可以缩小但不能扩大:

    ClassNotFoundException --> Exception(大)

多态

  1. 多态是方法的多态,属性没有多态
  2. 存在条件:继承关系,方法需要重写,父类引用指向子类对象!father f1 = new son();

属性赋值的先后顺序

  1. 默认初始化
  2. 显示初始化
  3. 构造器赋值
  4. 通过“对象.方法”或者“对象.属性”赋值

包装类

  1. 面试题一
//IntegerCache为Integer类的缓存类,默认缓存了-128~127的Integer值,如遇到[-128,127]范围的值需要转换为Integer时会直接从IntegerCache中获取,不用再去new。目的:提高效率
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j);//false

Integer m = 1;
Integer n = 1;
System.out.println(m == n);//true

Integer x = 128;
Integer y = 128;
System.out.println(x == y);//false

2.面试题二

//三目运算符比较基本数据类型,所以在编译阶段自动拆箱为 int 和 double 类型,由于三目运算符要求 表达式2 和 表达式3 类型一致,所以在编译阶段自动类型提升(即 int 自动类型转换为 double 类型),再自动装箱为Object,输出时使用多态调用重写的toString();即Double包装类的toString();
Object o1 = true ? new Integer(1) : new Double(2.0);
        //默认调用toString方法
System.out.println(o1);//1.0 
System.out.println(o1.toString());// 1.0


包装类与基本数据类型与String类型的相互转换

  1. 基本数据类型—>包装类:调用包装类的构造器
int num = 10;
Integer in1 = new Integer(num);
System.out.println(int.toString());//10
  1. 包装类—>基本数据类型:调用包装类的xxxVaule()
Integer in1 = new Integer(12);
int num2 = in1.intValue();
System.out.println(num2);
  1. 基本数据类型、包装类—>String类型:调用String重载的valueOf(Xxx xxx)
//方式一:连接运算
int num1 = 10;
String str1 = num1 + "";

//方式二:调用String重载的valueOf(Xxx xxx)
double num2 =12.3;
String str2 = String.valueOf(num2);//"12.3"

Float d1 = new Float(13.3f);
String str3 = String.valueOf(d1);
  1. String类型—>基本数据类型,包装类:调用包装类的parseXxx(String s)
String str1 = "123";
int num1 = Integer.parseInt(str1);

String str2 = "true";
boolean b1 = Boolean.parseBoolean(str2);

单例设计模式

1.饿汉式

//饿汉式
public class Singleton1 {
    public static void main(String[] args) {
        Bank bank1 = Bank.getInstance();
    }
}

class Bank{
    //1.私有化类的构造器
    private Bank() {

    }
    //2.内部创建类的对象,且该对象也为静态
    private static Bank instance = new Bank();

    //3.提供公共的静态方法,返回类的对象
    public static Bank getInstance(){
        return instance;
    }
}
  1. 懒汉式(未考虑线程安全版本)
//懒汉式,未考虑线程安全
public class Sington2 {
    public static void main(String[] args) {
        Order o1 = Order.getOrder();
        Order o2 = Order.getOrder();
        System.out.println(o1 == o2);
    }
}

class Order{
    private Order(){

    }

    private static Order order = null;

    public static Order getOrder(){
        if (order == null){
            order = new Order();
        }
        return order;
    }
}

饿汉式和懒汉式区别:从名字上来说,饿汉和懒汉,饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,而懒汉比较懒,只有当调用getInstance()的时候,才回去初始化这个单例。 另外从以下两点再区分以下这两种方式:

  1. 线程安全: 饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题, 懒汉式本身是非线程安全的,为了实现线程安全有几种写法,上面代码还未实现。

  2. 资源加载和性能: 饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成, 而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

执行顺序

静态代码块:用staitc声明,jvm加载类时执行,仅执行一次
构造代码块:类中直接用{}定义,每一次创建对象时执行。
执行顺序优先级:静态块/(当涉及到继承时,按照如下顺序执行:执行父类的静态代码块,并初始化父类静态成员变量;执行子类的静态代码块,并初始化子类静态成员变量)/,main(),构造块,构造方法。

Interface关键字/接口/匿名实现/代理模式

接口

接口是一种规范,接口本质上也是一个抽象类,不过只包含常量和方法。

接口的特点

  1. 接口用interface来声明
  2. 接口中可以声明成员变量,成员变量都是默认public static final修饰的。
  3. jdk1.7之前,接口中所有的方法都是抽象方法
  4. 接口中没有构造器(不能声明构造器)

注意

  1. 接口可以多继承接口的
  2. 接口只能被类实现
  3. 实现接口要重写接口中的所有的抽象方法
  4. 接口主要是用于被实现的(面向接口编程)

接口和抽象类的区别

  1. 接口和抽象都不能有实例

  2. 抽象类中可以有构造可以有普通方法和普通的成员变量,接口中只能声明静态公共常量(public static final),默认都是抽象方法

  3. 接口是需要被实现的,抽象类是需要被继承的

  4. 抽象类如果子类不想实现抽象类中的方法,那么该子类也必须是抽象类

  5. 接口可以多继承接口,实现类可以多实现接口,抽象类只能单继承

  6. 抽象类是重构的结果,接口是设计的结果

接口的4种实现方式

先解释一下匿名对象和匿名类。

匿名对象:匿名对象是没有名字的实体,也就是该实体没有对应的变量名引用,创建的匿名类的对象只能调用一次,匿名对象只在堆内存中开辟空间,而不存在栈内存的引用,而且每次创建匿名对象都是不同的对象。

匿名类: 匿名类 匿名类是不能有名称的类,所以没办法引用它们。必须在创建时,作为new语句的一部分来声明它们。匿名类相当于在定义类的同时再新建这个类的实例定义.

若要实现接口,先创建一个接口。

 interface Usb{	
 //数据传输开始的方法
 	public  void start();	
 //数据传输结束的方法
 	public void stop();
 }

再创建一个类,传入UBS接口的实现类,可以体现接口的多态性(计算机可以加载打印机,U盘等等)

class Computer {
	public static void transferData(USB usb) {
		usb.start();		
		System.out.println(" **  设备运行的过程  ** ");								
		usb.stop();
	}
}

然后就可以实现接口了 main

先创建一个计算机

Computer computer = new Computer();

再传入想运行的设备(将数据线插入USB中)

  1. 接口的非匿名对象的非匿名实现类
Usb printer = new Printer();
computer.transferData(printer);//传输数据

Printer类是已经创建好的,以下:

class Printer implements USB {
	public void start() {
		System.out.println("打印机设备开始运作:");
	}
	public void stop() {		
		System.out.println("打印机设备停止运作!");
	}
}
  1. 接口的匿名对象的非匿名实现类
computer.transferData(new Flash());

Flash类是已经创建好的,以下:

// 具体的设备U盘
class Flash implements USB {	
	public void start() { 
	//jdk1.8以后这里不用加@Override
		System.out.println("U盘设备开始运作:");
	}	
	public void stop() {		
		System.out.println("U盘设备停止运作!");	
	}
}
  1. 接口的非匿名对象的匿名实现类
	USB phone = new USB() {		
		public void stop() {			
			System.out.println("电话设备停止运行!");
		}		
		public void start() {			
			System.out.println("电话设备开始运行");				
			}
		};
	computer.transferData(phone);

显然,不需要单独创建Phone类

  1. 接口的匿名对象的匿名实现类
 computer.transferData(new USB(){
 		public void start() {
 			System.out.println("电话设备开始运行");
 		}
 		public void stop() {
 			System.out.println("电话设备停止运行!");
 		}
 });

显然,不需要单独创建Phone类,也不需要单独创建phone对象。
最后,匿名实现类适合什么时候用呢??比如,突然,想要运行一下电话设备,但以后再也不运行了,就用这个接口匿名对象类实现。

接口的应用之一:代理模式

  • 意图:为其他对象提供一个代理以控制对这个对象的访问。

  • 主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。

  • 何时使用:想在访问一个类时做一些控制。

  • 如何解决:增加中间层。在代理类中创建代理接口的对象,构造时传入被代理类(实现多态,所以接口类就行),并创建用于控制的方法。

静态代理

先创建代理接口

// 代理接口,可以实现浏览功能
interface NetWork{//网络
	public void browse();//浏览
}

再创建一个被代理类

// 被代理类
class RealServer implements NetWork{
	@Override	
	public void browse() {
		System.out.println("上网浏览信息");	
	}
}

最后创建代理类(四个部分)

  1. 私有成员:接口对象

  2. 构造器:传入外界的接口对象,拷贝给成员对象

  3. 成员方法:随便(安全控制,或者进程外的访问等等)

  4. 最后,重写接口中的抽象方法

  class ProxyServer implements NetWork{
      private NetWork netWork;

      public ProxyServer( NetWork netWork) {
        this.netWork = netWork;
      }

      public void check() {
        System.out.println("网络连接检查");
      }

      @Override
      public void browse() {
        check();
        netWork.browse();	
      }
  }

最后跑一下

public class ProxyTest {
	public static void main(String[] args) {
		NetWork net = new ProxyServer(new RealServer());
		net.browse();
	}
}

运行结果:网络连接检查
上网浏览信息

接口的应用之二:工厂模式

在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。(比如坐出租车时虽然你不知道太白南路怎么去,但告诉司机就行了,他会把你送到)

  • 优点:

    1. 一个调用者想创建一个对象,只要知道其名称就可以了。
    2. 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
    3. 屏蔽产品的具体实现,调用者只关心产品的接口。
    4. 实现了创建着和调用者的分离,即创建对象的具体过程屏蔽隔离,提高程序的灵活性
  • 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

  • 注意事项:作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。

/面向的对象的设计原则:ocp(开闭原则)/

分类:

  1. 简单工厂模式
  2. 工厂方法模式
  3. 抽象工厂模式
    核心:实例化对象,用工厂替代new操作
工厂模式的实现

我们将创建一个 Car 接口和实现 Car 接口的实体类。然后定义工厂类 eFactory。

  1. 创建一个Car 接口
interface Car{
	void run();
}
  1. 实现 Car接口的实体类
class Audi implements Car{
	@Override
	public void run() {
		System.out.println("奥迪run");
	}
}

class BYD implements Car{
	@Override
	public void run() {
		System.out.println("BYD run");
	}
}
  1. 定义工厂类 Factory
class Facatory{
	public static Car getCar(String type) {
		if("奥迪".equals(type)) {
			return new Audi();
		}else if("比亚迪".equals(type)) {
			return new BYD();
		}else {
			return null;
		}
	}
}

最后,跑一下

public class FactoryTest {

	public static void main(String[] args) {
		  Factory factory = new Factory();
	
	      Car audi = factory.getCar("奥迪");
	      audi.run();
	      Car byd = factory.getCar("比亚迪");
	      byd.run();
	   }
}

运行结果:奥迪run
BYD run

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值