Day11面向对象入门:内部类、内存分析、单例设计模式、简单工厂设计模式、基本数据类型包装类、String类

版权声明:仅供学习使用! https://blog.csdn.net/qq_34971756/article/details/89960428

一、内部类

内部类:一个类里声明另外一个类,内部类可声明成public或private
变量:成员变量、静态变量、局部变量
内部类:
成员内部类、静态内部类、接口内部类、局部内部类、匿名内部类

1、成员内部类

    public class Outter {
    	 String str1="字符串1";
    	//成员内部类
    	public class Inner{
    		String str1="内部类字符串";
    		public void print() {
    			System.out.println(str1);
    			System.out.println(Outter.this.str1);
    		}
    	}
    	}
    //成员内部类
    public class Test01 {
    	public static void main(String[] args) {
    		//创建成员内部类对象的语法
    		Inner in = new Outter().new Inner();
    		in.print();
    	}
    }

输出
在这里插入图片描述

2、静态内部类

(1)为什么静态内部类不能调用外部类的非静态属性?
创建静态内部类的对象,不会创建外部类的对象,外部类的属性就不会存在与堆内存中,就没有办法调用到

(2)为什么静态内部类可以调用外部类的静态属性?
创建静态内部类对象时,先把外部类的字节码文件加载到方法区中,并扫描该文件中的静态属性,然后放入静态常量区

    public class Outter {
    	String str1="外部属性1";
    	static String str2="外部静态属性";
    	
    	public static class Inner{
    		String str3="内部属性";
    		public void print() {
    			System.out.println(str2);
    			System.out.println(str3);
    		}
    	}
    }
    //静态内部类
    public class Test01 {
    	public static void main(String[] args) {
    		//创建静态内部类对象的语法
    	Inner in = new Outter.Inner();
    	in.print();
    }
    }

输出
在这里插入图片描述

3、接口内部类

    public interface IInterface {
    	public class Inner{
    	public void method() {
    		System.out.println("接口内部类");
    	}
    	}
    	}
    //接口内部类
    public class Test01 {
    public static void main(String[] args) {
    	Inner in = new IInterface.Inner();
    	in.method();
    }
    }

输出:接口内部类

4、局部内部类

只能在外部类里创建内部类的对象
局部内部类只能访问方法中的final类型的局部变量,因为final定义的局部变量相当于一个常量,它的生命周期超出方法运行的生命周期。

    //局部内部类
    public class Outter {
    	public void method() {
    		class Inner{
    			public void print() {
    				System.out.println("局部内部类");
    			}
    		}
    	Inner in = new Inner();
    	in.print();
    	}
    }
    public class Test01 {
    	public static void main(String[] args) {
    		Outter out = new Outter();
    		out.method();
    	}
    }

5、匿名内部类

匿名内部类的外部类是抽象类。
之前介绍的内部类只是单一的类,并没有继承或者实现任何类或接口,实际上也是可以继承一个抽象类或实现一个接口。
匿名对象:没有明确声明的对象,只使用一次的对象,即没有任何一个具体的对象名称引用它。这种操作可以节约内存
匿名内部类(匿名子类):创建了一个没有名字的类,继承了MyClass,重写了method方法。
多态:创建该匿名内部类的对象,赋值给父类的引用。

(1)匿名内部类

    public abstract class MyClass {	
    	public abstract void method();
    }
public class Test01 {
public static void main(String[] args) {
	MyClass m = new MyClass() {
		
		@Override
		public void method() {
			System.out.println("匿名内部类");		
		}
	};
	m.method();
}
}

输出:匿名内部类

(2)接口类匿名内部类

public interface IInterface {
	public void method();
}
public class Test02 {
	public static void main(String[] args) {
		IInterface I=new IInterface() {		
			@Override
			public void method() {
				System.out.println("接口匿名内部类");
			}
		};
		I.method();
	}
}

输出:接口匿名内部类

(3)匿名内部类的应用

public interface ICode {
	public void runTime();
}
//计算for循环运行的时间
//匿名内部类创建的对象作为testCode方法的输入
public class Test01 {
	public static void main(String[] args) {
		long testcode = testCode(new ICode() {
			
			@Override
			public void runTime() {
				String str="";
				for(int i=0;i<10000;i++) {
					str+="哈哈";
				}
			}
		});
		System.out.println(testcode);
	}
	
	public static long testCode(ICode c) {
		long time1 = System.currentTimeMillis();
		c.runTime();
		long time2 = System.currentTimeMillis();
		return time2-time1;
	} 
}

二、内存分析

: 调用方法就会开辟空间,并存储商法中的局部变量,方法一旦执行完毕,开辟的空间就会被立刻回收。
: 存储对象
方法区: 存储字节码文件,项目结束时被清空。
静态常量区: 存储static修饰的变量,项目结束时被清空。
常量区: 存储final及字面值常量,项目结束时被清空。
在这里插入图片描述
在这里插入图片描述

三、单例设计模式

单例设计模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要有三点:
(1)构造方法私有化
(2)声明一个本类对象
(3)给外部提供一个静态方法获取对象实例

在项目中为什么要使用单例,单例有什么好处?
1、在设计一些工具类的时候(通常工具类,只有功能方法,没有属性)
2、工具类可能会被频繁调用

目的是为了节省重复创建对象所带来的内存消耗,从而来提高效率。

能不能使用构造方法私有化+静态方法来替代单例?

两种实现方式:

1、饿汉式

在类被加载后,对象被创建,到程序结束后释放。
占用内存时间长,效率高,线程安全。立刻加载

    public class Hungry {
    	private static Hungry m= new Hungry();
    	Hungry() {}
    	public static Hungry getInstance() {
    		return m;
    	}
    	public void method() {
    		System.out.println("饿汉式");
    	}
    }
    public class Test01 {
    	public static void main(String[] args) {
    		Hungry m1=Hungry.getInstance();
    		Hungry m2=Hungry.getInstance();
    		System.out.println(m1==m2);
    	}
    }

结果:true

2、懒汉式

在第一次调用getInstance方法时,对象被创建,到程序结束后。
占用内存时间短,效率低,线程不安全(在多线程访问时会有安全问题)。延时加载

    public class Lazy {
    	static Lazy m = null;
    	private Lazy() {}
    	public static Lazy getInstance() {
    		if(m == null) {
    			m = new Lazy();
    		}
    		return m;
    	}
    	public static void method() {
    		System.out.println("哈哈哈哈");
    	}
    }
    public class Test01 {
    	public static void main(String[] args) {
    
	    	Lazy m1 = Lazy.getInstance();
			Lazy m2 = Lazy.getInstance();
			m1.method();
			m2.method();
    }
    }

结果:
哈哈哈哈
哈哈哈哈

四、简单工厂设计模式

简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式。

当使用者和被使用者两者之间耦合,产生依赖,当被使用者改变时,会影响使用者。可使用工厂模式来降低两者之间的依赖。

需求:娃娃工厂生产瓷娃娃和布娃娃。

	//	娃娃抽象类
    public abstract class Doll {
    	public abstract void use();
    }
//瓷娃娃
public class CiDoll extends Doll{

	@Override
	public void use() {
		System.out.println("瓷娃娃是摆设!");	
	}
}
//布娃娃
public class BuDoll extends Doll{

	@Override
	public void use() {
		System.out.println("布娃娃是玩偶!");	
	}
}

使用单例设计模式(懒汉式)创建一个工厂
娃娃工厂类具有生产娃娃的方法

//娃娃工厂类
public class DollFactory {
	public static final int CI_DOLL=1;
	public static final int BU_DOLL=2;
	 //懒汉式
	private static DollFactory factory = null;
	private DollFactory() {}
	public static DollFactory getInstance() {
		if(factory == null) {
			factory = new DollFactory();
		}
		return factory;
	}
	
	//生产娃娃
	public Doll ProduceDoll(int type) {
		Doll doll = null;
		switch(type){
			case CI_DOLL:
				doll=new CiDoll();
				break;
			case BU_DOLL:
				doll=new BuDoll();
				break;
			default:
				break;
		}
		return doll;
	}
	
}
public class Test01 {
	public static void main(String[] args) {
		DollFactory factory = DollFactory.getInstance();
		Doll doll = factory.ProduceDoll(DollFactory.CI_DOLL);
		doll.use();
		Doll doll2 = factory.ProduceDoll(DollFactory.BU_DOLL);
		doll2.use();
	}
}

输出:
瓷娃娃是摆设!
布娃娃是玩偶!

五、基本数据类型包装类

基本数据类型不具有对象的特性,不能满足某些特殊的需求。从JDK中可以知道,Java中的很多类的很多方法的参数类型都是Object,即这些方法接收的参数都是对象,同时,又需要用这些方法来处理基本数据类型的数据,这时就要用到包装类。

基本数据类型 基本数据类型包装类
int Interger
char Character
float Float
double Double
byte Byte
long Long
short Short
boolean Boolean

装箱:基本数据类型 --> 包装类

Integer integer = Integer.valueOf(10);

拆箱:包装类 --> 基本数据类型

		int i = integer.intValue();

自动装箱 基本类型—引用类型:整型在特定情况下会自动转换为Integer类型。
自动拆箱 引用类型—基本类型:Integer类型在特点情况下会自动转换为整型。
Integer类:
paeseInt()方法:将一个字符串转换成基本数据类型;
valueOf(int i) : 返回一个表示指定的 int 值的 Integer 实例。

六、String类

public static void main(String[] args) {
		
		//String类的常用方法
		
		String str = "123abcDEF123";
		
		str = str.concat("4567");在末尾追加字符串,并返回新的字符串
		str = str.substring(2);从开始下标处截取到末尾,并返回新的字符串
		str = str.substring(2, 9);从开始下标(包含)处截取到结束下标(不包含),并返回新的字符串
		str = str.toLowerCase();转小写,并返回新的字符串
		str = str.toUpperCase();转大写,并返回新的字符串
		
		str = "   123 abcd EDF   123          ";
		
		str = str.trim();去掉首尾空格,并返回新的字符串
		str = str.replace(" ", "a");把空字符替换成 a字符串
		
//		System.out.println(str);//123aabcdaEDFaaa123
		
		System.out.println("该字符串的字符个数:" + str.length());
		System.out.println("比较字符串内容是否相同:" + str.equals("123aabcdaEDFaaa123"));
		System.out.println("比较字符串内容是否相同(不区分大小写):" + str.equalsIgnoreCase("123AAbcDaedFaaa123"));
		
		System.out.println("判断是否以某个字符串开头:" + str.startsWith("123"));
		System.out.println("判断是否以某个字符串结尾:" + str.endsWith("aaa123"));
		
		int indexOf1 = str.indexOf(97);查询ASCII
		int indexOf2 = str.indexOf("2");查询目标字符串在原字符串中的下标
		System.out.println("获取下标上的单个字符:" + str.charAt(7));
		
		将其他类型转换为字符串
		String valueOf = String.valueOf(true);
		System.out.println(valueOf);
		
		String s = true+"";
		System.out.println(s);
	}
	```

猜你喜欢

转载自blog.csdn.net/qq_34971756/article/details/89960428