史上最全讲解: JAVA中的单例模式,内部类与异常

史上最全讲解: JAVA中的单例模式,内部类与异常


设计模式共有23种设计模式,是前辈对代码开发经验的总结.不仅仅Java,其它面向对象语言也有.

单例模式

单例模式是保证类只存在一个对象.实现方式主要有懒汉式与饿汉式.

懒汉模式

懒汉式:调用功能的时候才创建对象.

package com.shsxt.single02;

public class SingleLazy {
	//1私有的静态的类属性
	private static SingleLazy single = null;
	//2.空构器私有
	private SingleLazy(){
		
	}
	//3.公共的访问方式 公共的静态的上锁的返回值为SingleLazy的方法
	public static synchronized SingleLazy getInstance() {
		if(SingleLazy.single==null){
			SingleLazy.single = new SingleLazy();
		}
		return SingleLazy.single;
	}
}

饿汉模式

类第一次加载完成之后就创建对象.

package com.shsxt.single02;
//饿汉模式 线程安全
public class SingleHungry {
	//类一加载完就创建对象
	private static SingleHungry single = new SingleHungry();
	//构造器私有
	private SingleHungry(){
		
	}
	//公共的访问方式 静态方法 返回一个SingleHungry类型的对象single
	public static SingleHungry getInstance (){
		return single;
	}
}



二者优缺点

懒汉式:线程不安全(多个线程操作同一份资源的时候 有可能会出现线程不安全)
饿汉式:线程安全

工厂模式

工厂去创建对象用户拿去用

代理模式

为其他对象提供一种代理以控制对这个对象的访问

  • 注意:真实角色需要与代理角色实现相同的接口,代理需要持有真实角色的引用
  • 好处:减少与真实角色的交流,提高代码的安全性,解耦,便于后期维护,代理角色可以扩展功能
  • 实例: 项目经理与HR招聘的过程中,项目经理需要将部分功能交于HR
package com.shsxt.single01;

public class StaticPolxy {
	public static void main(String[] args) {
		Manager manager = new Manager();//招聘经理创建好了把地址值传给HR
		//HR找到对应的地址值才可以.
		HR hr = new HR(manager);
		hr.recruit();
	}
}

interface Recruitment{
	public void recruit();
}

class Manager implements Recruitment{

	@Override
	public void recruit() {
		System.out.println("录用");
		
	}
	
}

class HR implements Recruitment{
	Manager manager;//定义一个Manager类型的manager参数
	//先有项目经理后有HR
	//将manager定义为一个成员属性传给recruit方法
	//也可以定义为recruit方法的一个参数传进来
	//但是重写不可以 接口里的方法没有参数
	public HR(Manager manager){
		super();
		this.manager = manager;
	}
	@Override
	public void recruit() {
		System.out.println("招聘");
		manager.recruit();
		//用到了Manager里的方法 
		
	}
	
}

内部类

类中定义的类,当一个类中的成员也是另外一个事务的时候(汽车的发动机,人的心脏器官),这个事务就可以使用内部类定义

成员内部类

  • 定义:内部类处于外部类的成员位置,是外部类的成员就可以使用成员修饰符,是一个类就有类的特性,可以继承父类,可以实现接口.
  • 注意:
    1.内部类中可以使用外部类中的所有内容,包括私有的
    2.静态内部类以外的其它内部类不可以定义静态的内容,除了静态的常量
    3.外部类中使用内部类的成员,通过内部类的对象
public class Outer01 {
	private int a=5; //成员变量
	
	String haha="123";
	
	//内部类
	public class Inner extends A{
		int b=3; //内部类中的成员变量
		static final int c=10;
		
		String haha="456";
		
		public void inner(){
			
			String haha="789";
			
			System.out.println("我是内部类中的成员方法");
			System.out.println(b);
			System.out.println(a);
			
			//局部haha
			System.out.println(haha);
			//内部类成员haha
			System.out.println(this.haha);
			//外部类成员haha
			System.out.println(Outer01.this.haha);
		}
	}
	//外部类中的成员方法
	void outer(){
		//内部类对象
		Inner in=new Inner();
		System.out.println(in.b);
	}
}
class A{}
//另外一个java文件
package com.shsxt.inner03;

/*
 * 内部类测试类
 */
public class Test {
	public static void main(String[] args) {
		//成员内部类依赖于外部类的对象使用
		//创建成员内部类对象1
		Outer01 out=new Outer01();
		//Inner in=out.new Inner();
		Outer01.Inner in=out.new Inner();
		System.out.println(in.b);
		in.inner();
		//创建成员内部类对象2
		Outer01.Inner in2=new Outer01().new Inner();	
	}
}

静态内部类

  • 定义:成员内部类一旦被静态修饰符static修饰,就是静态内部类.
  • 注意:
    1.如果在外部类中使用静态内部类的成员,需要跟随内部类对象使用,如果使用静态内部类中的内容直接类名.调用
    2.如果在静态内部类中使用外部的成员,都要跟随外部对象使用,如果使用静态内容,在内部类中可以直接使用
public class Outer02 {
	private int a=5;
	private static int b=10;
	//静态内部类
	static class Inner{
		String name="zhangsan";
		static int age=15;
		
		void test1(){
			System.out.println("内部类中的成员方法");
			System.out.println(name);
			System.out.println(age);
			Outer02 out=new Outer02();
			System.out.println(out.a);
			System.out.println(b);
		}
	}
	
	void outer(){
		System.out.println(Inner.age);
		Inner in=new Inner();
		System.out.println(in.name);
		in.test1();
	}
}

私有内部类

  • 定义:成员内部类一旦被私有修饰符private修饰就是私有内部类.
  • 注意:
    1.私有内部类只能在当前所定义的外部类中使用,其他类无法使用
    2.在外部类中通过内部类的对象使用内部类的内容,保护私有内容
public class Outer03 {
	private int a=5;
	//私有内部类
	private class Inner{
		private int b=10;
		
		void inner(){
			System.out.println(a);
			System.out.println(b);
		}
	}
	
	void outer(){
		Inner is=new Inner();
		System.out.println(is.b);
	}
}

局部内部类

  • 定义:定义在一个类中的方法当中的类.局部内部类只能在当前定义的方法中使用,外部类中的其他方法无法使用局部内部类.
  • 注意:
    局部内部类中使用当前所在类中的参数时,参数默认被final修饰,在局部内部类中使用不能修改参数的值
public class Outer04 {
	String name="lisi";
	void test(int i){
		//局部变量
		int a=10;
		//局部内不类
		class Inner{
			void inner(){
				System.out.println(a);
				System.out.println(name);
				
				System.out.println(i);
			}
		}
		//方法中通过内部类的对象使用成员
		new Inner().inner();
	}
	void outer(){
		//new Inner().inner();
	}
}

匿名内部类

  • 定义: 如果某个类单纯只是为了实现某个接口(重写某个抽象方法)的实现类.而本身没有自己的作用,这时候可以使用匿名内部类
package com.shsxt.inner03;

public class Anonymous {
	public static void main(String[] args) {
		//接口的匿名对象调用其中的一个方法
		new Study(){

			@Override
			public void study() {
				System.out.println("好好学习");
				
			}

			@Override
			public void sleep() {
				System.out.println("好好睡觉");
			}
			
		}.study();
		//匿名对象调用很多方法
		Study s = new Study(){

			@Override
			public void study() {
				System.out.println("好好学习");
				
			}

			@Override
			public void sleep() {
				System.out.println("好好睡觉");
				
			}
			
		};
		s.study();
		s.sleep();
		
		new Anonymous().test(new Study(){

			@Override
			public void study() {
				System.out.println("好好学习");
				
			}

			@Override
			public void sleep() {
				System.out.println("好好睡觉");
				
			}
			
		});
		new Anonymous().test(s);
	}
	void test(Study s){
		s.study();
		s.sleep();
	}
	
	
}

interface Study{
	void study();
	void sleep();
}

Lambda表达式

  • 作用:用来简化匿名内部类
  • 前提:函数式接口(只有一个抽象方法的接口),修饰符@FunctionalInterface
  • 语法格式:
      () -> {}
      ()抽象方法的参数列表
      ->箭头函数或者参数列表,具有上下文推导的作用
      {}抽象方法的方法题;
  • 注意:
    1.lamdba表达式最全写法不要忘记{}后的分号
    2.如果方法体只有一句,可以省略花括号{};
    3.如果抽象方法有参数,参数类型可以省略
    4,抽象方法的参数只有一个,()可以省略
    5.如果与具体只有一句,是return的话,前后{}与return关键字可以一起省略
package com.shsxt.inner03;

public class Lambda04 {
	public static void main(String[] args) {
		new Sleep(){

			@Override
			public int sleep(int a) {
				System.out.println("好好睡觉");
				return 1;
				
			}
			
		}.sleep(1);
		
		Sleep s= (a) -> {
			System.out.println("好好睡觉");
			return 1;
		};
		
		s = (a)->{System.out.println("好好睡觉");
		return 1;};
		
		
		Eat e = (a)-> 0;
		System.out.println(e.eat(1));
			
		}
		
	}


@FunctionalInterface
interface Sleep{
	int sleep(int a);
}
@FunctionalInterface
interface Eat{
	int eat(int a);
}

异常Exception

在java中,异常与错误是两个不同的概念,throwable分为exception和error.错误error一般是由虚拟机产生的,不需要关注.异常分为编译异常和运行异常.throw制造异常, throw new NullPointerException();

编译异常 CheckedException

出现不处理程序无法执行,一般有两种处理方式

  • throws抛出异常 把异常抛给上一层,谁用谁处理
  • try…catch(){}捕获异常
    格式:
try..catch(){}
* 		try{
* 			可能会出现异常的代码
* 		}catch(FileNotFoundException e){
* 			执行...
* 
* 		}catch(NullpointerException e){
* 			执行...
* 
* 		}catch(Exception e){
* 			接盘侠
* 		}
* 			....
* 		 fially{
* 			无论是否会出现异常,都会执行的代码
* 		}
  • 注意:
    1.一个try后可以跟多个catch
    2.如果try中的代码没有出现异常,正常执行完毕,执行finally中的内容结束
    3.如果try中出现异常,下面的代码不会执行,直接进入对应的catch中
    4.finally无论是否出现异常,都会执行的代码
public class ExceptionDemo02 {
   public static void main(String[] args) {
   	try {
   		System.out.println("try开始了");
   		test();
   		System.out.println(5/0);
   		System.out.println("try结束了");
   	} catch (FileNotFoundException e) {
   		e.printStackTrace();
   	} catch(ArithmeticException e){
   		System.out.println("出现数学异常了");
   	} catch(Exception e){
   		e.printStackTrace();
   	} finally{
   		System.out.println("最后的最后我们都会狗带...");
   	}
   }
   
   static void test() throws FileNotFoundException{
   	//对象是异常的形式出现
   	//throw new NullPointerException();
   	
   	InputStream is=new FileInputStream("D:/test.txt");
   }
}

常见的异常Exception

1.空指针异常

  •  2.数组越界异常IndexOutOfBoundryException
    
  •  3.数学异常 ArithmeticException
    
  •  4.类型转换异常 ClassCastException
    
  •  5.数组长度负数异常 NegativeArraySizeException
    
  •  6.数学转换异常 NumberFormatException
    
  •  7.空指针异常 NullPointerException
    

自定义异常

  • 自定义异常类步骤
    1.继承java.lang.Exception声明自己是异常类
    2.方法的适当语句制造异常 throw
    3.在方法声明部分用throws语句声明该方法可能抛出异常
    4.调用该方法的时候用try catch语句捕获异常
    自定义异常可以更好地提示发生的异常是什么,更加灵活!
  • 实例
package com.shsxt.definedexception;

public class DefinedException02 {
	public static void main(String[] args) {
		try {
			Users users = new Users("111");
			System.out.println(111222);
		} catch (MyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			System.out.println("我是finally");
		}
	}
}

class Users {
	//private String name;
	private String password;
	
	public String getPassword() {
		return password;
	}
	public Users() {
		super();
	}
	public Users(String password) throws MyException {
		if("111".equals(password)){
			throw new MyException("密码错误,请重新输入,谢谢!");
		}
		this.password = password;
	}
}

class MyException extends Exception {
	private String msg;
	public String getPassword() {
		return msg;
	}

	public void setPassword(String msg) {
		this.msg = msg;
	}
	
	public MyException() {
		super();
	}
	public MyException(String msg) {
		super(msg);
		this.msg = msg;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值