java学习——基础名词、基本数据结构、基本函数、基本内容

Collection体系、maven(一、1.(4))、

一、基础名词

(1)OOP(Object Oriented Programming):面向对象编程

  AOP(Aspect Oriented Programming):面向切面编程

相比较于面向切面编程,面向对象的具体体现是,类与类之间调用会实体化另一个类,或者可以说成JavaBean和JavaBean之间相互调用,会在调用时实体化另一个Bean对象,所以叫做面向对象编程。而面向切面编程,在调用时不会实体化一个Bean对象,而是(这里以Spring举例)会从接口中获取方法,通过xml配置文件来依赖另一个接口(依赖关系通过xml文件中的组装实现),实体化放在了最后应用传递参数的时候,只一次实体化。ACCP软件工程师——使用SSM框架开发企业级应用 8.0版的P129到P135的例子,比较形象。

面向接口编程优缺点:
优点:①程序结构清晰,使用方便。②接口合理设计,可以实现并行开发,提高效率。③实现程序可插拔性,对于不同的需求切换不同的实现,降低了耦合度,系统越复杂这个优势会更明显。④允许多重实现,弥补了继承的缺陷。
缺点:①增加了设计的复杂度,如果程序不是很复杂,就只会增加工作量。②可能会降低代码的可复用性。③可能会降低程序的执行效率。

(2)JVM(Java Virtual Machine):java虚拟机

是一种用于计算设备的规范,是一个虚构出来的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的。作用是使java语言能在不同平台上运行时不需要重新编译,它只识别字节码——编译后的东西(理解为用目标计算机的码生成了java的标准码,然后就用这些码进行编译和编写不用重复此过程)
JVM的使命:
按照类的名字,加载、执行类。
准确的说应该是:
按照类的全限定类名,加载、执行类的字节码。(java这种OOP语言,所有的东西都得包含在类里面,因为JVM执行的最小单位就是类,而且只认全限定类名)

(3)全限定类名:

就是类名全称,也可以理解为其包括路径在内的类名,例如:java.lang.String
非限定类名:即单纯的类名,不包含路径。如String

(4)Maven:

①作用:解决包的传递依赖性造成的困扰
②作用过程:
·Maven首先按照你的要求,去仓库中按照编号找到你需要的那叠说明书。
·Maven查看了一下说明书旁边放的清单,发现这叠说明书依赖了另外几个牌子型号的说明书,于是继续在仓库里翻找。
·重复这个过程,直到找全所有需要的说明书。
·如果这些说明书之间存在冲突,解决之(稍后会讲到)。
·将所有用到的说明书下载到本地,然后拼装一个很长的classpath字符串,启动JVM(或者javac)。
参考链接:Java包管理的那些事4——Maven

(5)向下转型、向上转型

参考链接:Java 转型问题(向上转型和向下转型)

//father是一个父类,son是他的子类
Father f1 = new Son();   // 这就叫 upcasting (向上转型)
// 现在 f1 引用指向一个Son对象

Son s1 = (Son)f1;   // 这就叫 downcasting (向下转型)
// 现在f1 还是指向 Son对象

Father f2 = new Father();
Son s2 = (Son)f2;       // 出错,子类引用不能指向父类对象

(6)耦合

设计程序要做到高内聚低耦合,耦合就是对其它文件的依赖,理想结果就是除了接口以外不调用任何其他文件的内容,或对象之间的依赖。耦合度高造成的后果就是要改其中一个,就得全部都改,维护成本高。

(7)反射

见下面基本内容中的反射

(8)重载、重写

重载:函数名相同,参数列表不同。(不能仅依靠返回值来重载)@overload
重写:子类的方法覆盖父类的方法,要求方法名和参数都相同@override

(9)IoC(Inversion of Control):控制反转、依赖注入

也称为依赖注入(Dependency Injection ,DI),是面向对象编程的一种设计理念,用来降低程序代码之间的耦合度,在Spring部分出现。
参考链接:依赖注入和控制反转的理解
例子: 这里的Spring目的是将service部分的文件赋值和创建JavaBean(通过调用其中setter方法,赋值),使得组件之间通过配置文件相结合,而不是通过代码,直接调用来结合。暂时觉得还是用了一个factory思想,将调用方中的new 被调用方();这一步提出来了,放到factory也就是Spring中去,这样做改动的时候就不用改所有的调用方中的new等代码(多个),只需要配置applicationContext.xml文件中的bean文件(一个),而把service.java文件当作一个接口,可以配置多套文件使用同一个接口。

//Spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
	<bean id="helloSpring" class="test_Spring.HelloSpring">
		<property name="who">
			<value>Spring</value>
		</property>
	</bean>
</beans>
//这里其实就是MyBatis配置完之后的service.java,存的是方法,返回的是实例化之后的东西(其实并不是说service这里只是使用简单的例子进行举例,并没有结合web项目过程)
package test_Spring;

public class HelloSpring {
	private String who = null;
	public void print() {
		System.out.println("Hello," + this.getWho() + "!");
	}
	public String getWho() {
		return who;
	}
	public void setWho(String who) {
		this.who = who;
	}	
}
//test文件(Junit)
package test_Spring;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

class test {

	@Test
	void test() {
		
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		HelloSpring helloSpring = (HelloSpring) context.getBean("helloSpring");
		helloSpring.print();
	}

}

(10)API(Application Program Interface):应用程序接口

就是程序所提供的接口,一般是方法之类的东西
在Java语言程序设计(基础篇)中:应用程序接口也称为库,包括开发Java程序而预定义的类和接口。

(11)依赖注入–见(9)

(12)接口类

①不可以含有除了public final以外的变量(默认就会将定义的变量用用final修饰)
②是一组方法的抽象
③不可以有具体方法(java8之后可以有默认方法)
调用前需要先用他的实现类进行实例化,才可以用(接口类就像一张空白的表格,有类别,名字,使用方式等项,但是没有被填;它的实现类就是怎么填这些项,填完就可以使用了,实现类可以不止一个实现不同类别)
举例:test_blog中Dao层的接口类—UserMapper.java类是用MyBatis中UserMapper.xml进行实现的,MyBatis管理实现类的生命周期和实例化,所以配置完MyBatis之后不用再去管理实现类。这里的Service

(12)抽象类

1.定义时会使用abstract修饰
2.抽象类不能被实例化,必须被继承。
3.其中可以写变量且赋值。
4.除非其子类也是抽象类,否则抽象类中的抽象方法必须被重写。

(13)EJB(EnterPrise JavaBean 企业级JavaBean)

是一种已经被Spring淘汰掉的跨平台构建体系系统。
参考链接:EJB到底是什么,真的那么神秘吗??

(14)线程安全和线程不安全

线程安全:通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况
线程不安全:指不提供加锁机制保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。
解决办法(1)synchronized (2)Lock

(15)序列化

implements java.io.Serializable?????????????????????

(16)映射、映射器

映射器:在MyBatis中是由接口+xml文件构成

(17)classloader:类加载器

当运行Java程序时,首先运行JVM(Java 虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。

(18)bytecode verifier:字节码验证器

java安全–字节码校验
使用字节码验证器(bytecode verifier)的程序来检验字节码的合法性,确保字节码不会违反Java的安全规范

(19)引用

浅谈Java中的对象和引用
可以理解成地址,

 	A a = new A();	//这里的a就是对A的引用

(20)导入

1.明确导入(specific import):

    import java.util.Scanner; 

2.通配符导入(wildcard import):

    import java.util.*; 

二者在性能上是没有什么差别的

(21)Java方法签名(重载的很好解释)

方法签名就由方法名+形参列表构成,也就是说,方法名和形参数据类型列表可以唯一的确定一个方法,与方法的返回值一点关系都没有,这是判断重载(8)重要依据
参考链接:Java方法签名

(22)包装类

基本数据类型不具备对象属性,不能调用方法。
在这里插入图片描述
包装类可以:①和其他基本类型进行转换的方法。②字符串和本类型及包装类相互转换的方法。
如Integer:
在这里插入图片描述

(23)偏向锁、自旋锁、重量级锁

(1)偏向锁:于用户空间
(2)自旋锁、无锁、轻量级锁:于用户空间
(2)重量级锁:于操作系统空间

首先线程利用CAS机制对变量上的是偏向锁(即贴上自己的标签,检测到是自己标签的变量就直接访问),如果CAS过程中发生被占用的问题则产生自旋锁(即CAS过程),如果JVM检测到进程自旋锁过程重复太多次(现在是自适应的过程来判断多少是过多)则去申请重量级锁,由操作系统去分配线程的资源。

(24)CAS(CompareAndSwap)

以对变量加一操作为例
线程确定访问变量后读取变量值,在线程内完成加一的操作,然后在向变量中存储操作结果的时候,检测变量中数据是否发生改变,如果没有改变说明在这之前没有进程对此数据进行修改,如果数据发生改变,则重新读取后重新操作或者按照设定好的过程进行再次CAS

其中可能发生ABA问题,即检查的过程中发生从A被一个线程改变为B又被线程改变回A,则没办法判断是否正在被占用,解决方法为添加版本号。

(25)DCL(DOUBLE CHECK LOCK)

是在单例模式是现实出现的锁流程,在数据库事务等中也会涉及到
在单例模式中以.class文件的创建和初始化变量为例,

new #2 <T>
dup
invokespecid # 

在下面$$$$$$$$$$$准备在 Java学习——JVM(初步)中写因为例子涉及到类的初始化问题

(26)JDK(Java Development Kit)和 JRE(Java Runtime Environment)

JDK是Java的软件开发工具包,它包含的是JAVA的运行环境(JVM+Java系统类库)和JAVA工具。
安装下载等见毕设部分——准备项目bookstore项目中一、环境配置部分1. 安装部分
JRE是Java的运行环境,其中包括一个JVM和一些标准的类别函数库。

两者区别:你想了解JDK、JRE、JVM分别是什么及它们之间的有什么关联吗?
JDK包含了JRE,JDK 和 JRE 中都包含 JVM。也可以说JDK是JRE+Java的开发工具。
JDK用于开发,是给开发人员用的,JRE 用于运行java程序,和JVM是给普通用户使用的。如果只是运行Java程序,可以只安装JRE,无序安装JDK。也就是说:使用JDK开发完成的java程序,交给JRE去运行。
JRE包含了JVM+Java语言的核心类库。

(27)堆和栈

参考链接:【java】jvm内存模型全面解析
堆(heap):字符串常量和对象
栈(stack):这里放的是函数运行中的对象(引用,指向堆中的实际内存位置),基本数据类型就存在这里
方法区(元数据空间):静态方法和静态变量还有类加载器
本地方法栈、程序计数器(标记程序当前运行位置)

String str1 = "aaaa";	//这个"aaaa"存在堆中,str1是一个引用存在栈中
String str2 = "aaaa";	//这个str2指向的还是str1所指向的那个内存空间

栈(stack):存储基本类型,引用类型变量,方法
存取速度比堆快,仅次于寄存器,栈数据可以共享。但缺点是,栈中数据大小与生存周期是确定的,缺乏灵活性。
常量空间:

详细内容在基本内容中

(28)多态

1.引用多态:父类的引用可以指向本类和子类的引用
2.方法多态:
 ①创建本类对象时,调用的方法为本类方法
 ②创建子类对象时,调用的方法为子类重写的方法或者继承的方法->子类独存的方法无法通过父类引用调用
3.引用类型转换:
 ①向上类型转换(隐式)(Dog->Animal)
 ②向下类型转换(显示) (大->小,有风险)

(29)访问修饰符号

本类同包子类其他(不同包非子类)
private
默认(friendly)
protected
public

(30)JVM内存模型

在这里插入图片描述

②:
在这里插入图片描述

(31)单例模式

参考链接:单例模式的五种写法
几种写法:懒汉,饿汉,DCL(见(25))等

二、基本数据结构

部分的底层原理$$$$$$$$$$:List、set、Map的底层实现原理
对这几个Java数据结构的总结:List、set、Map的底层实现原理
这几个数据结构主要差异在于实现原理,其中的值可否重复,数据存储是否有序,可否包含null,继承自Collection还是,容量是否可以自增长,添加删除数据效率,get和set方面效率。
ArrayList:实现原理为数组
LinkedList:

数据结构实现原理值可否重复数据存储是否有序可否包含null继承自何处容量是否可以自增长添加删除数据效率get和set方面效率
ArrayList数组可重复有序可以可以(重新分配空间)最好是在添加在最后一位O(1),最坏是添加时空间已满重新分配内存并复制为O(n)以索引的方式的话(下标)O(1)
LinkedList双向链表可重复有序可以可以O(1)O(n) (需要遍历)
HashMap数据加链表或者数组加红黑树不可重复无序可以可以(涉及到阈值扩充)在没有扩充的时候,是O(1)经取hash值之后可能顺着链表遍历 O(1)
HashSethash表—数组(由HashMap实例支撑)不可重复无序可以Collection可以最好是在添加在最后一位O(1),最坏是添加时空间已满重新分配内存并复制为O(n)以索引的方式的话(下标)O(1)

1.Map<K,V>

参考链接;
Java Map 接口
Java中的Map及其使用
(1)暂时理解为一个接口,可以接受new HashMap<K,V>(); ,K为key,V为value,即key作为标识符,然后value作为key指向或者说代表的值或者数据类型,所以Map<K,V>是一个二维数组。
(2)使用

	//声明
	Map<String,List> map =null;
	//放入
	map.put("abc",userList);
	//取出其中的值
	List<User> users = map.get("abc");
(3)部分方法:

Map.entrySet():是取到此map中各个键值对映射关系的集合(是一个链表)。所以之后使用Map.entrySet().next()来取得下一个键值对映射关系,然后用过.getKey()和.getValue()来获取键值对的信息。Java中Map的entrySet()详解

2.HashMap<K,V>

线程不安全但是单线程性能高,HashTable线程安全
见1.Map<K,V>
hashmap一开始使用数组加链表,hashmap方法也是KV结构key和value,基本上是接受传过来的key,然后函数处理成整形数组下标,如果数组下标标记的位置已经有内容(这个叫hash冲突),那么就以这个位置(结点)为头节点,往下建立链表(链表的结点,也是数组中的位置),以此类推。和插入时一样,查找时,如果生成的下标位置中的内容不是我们要查找的,即key不同但是生成的下标一样,那么顺着链表向下找,总会找到。
循环就是链表A向下延申(增加结点)的时候恰巧延申到另一个能够指向A的结点(头结点的话现象比较明显)的链表(B链表),这样就会构成循环,导致找不到。

3.List<>和array

参考链接:Java中Array、List、ArrayList的区别

(1)List是一个接口,实现类为ArrayList和LinkedList。是一个有序集合,可以包含重复的元素,提供按索引访问的方式
  array(数组)和C的一样,获取数据快,但是删除数据开销大。
(2)使用

4.ArrayList和LinkedList

参考链接:Java中Array、List、ArrayList的区别
(1)ArrayList可以看作自动增长容量的数组。
  LinkedList是一个双链表,在添加和删除元素时具有比ArrayList更好的性能,但是在get和set方面弱于ArrayList。
(2)使用

	List<Intger> list_intger = new ArrayList();

(3)

5.entry

是构成map的元素,entry是一个键值对的映射关系(<K,V>)。

6.Set

Set继承自Collection,是用对应的Map所实现的,用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复。
其中HashSet是由hash表(实际上是一个HashMap实例)支持,不保证set的迭代顺序(即存储是无序的),允许使用null值。
使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不相等的话,返回false
HashSet和HashMap的区别:JAVA HashMap 和 HashSet 的区别
HashSet只存储对象而不是键值对,HashSet是实现的Set接口而不是Map,使用add(0放入set而不是put(),HashSet使用成员对象来计算hashcode值,而不是键值对,相对HasMap来说慢一些

7.hash表

容量:hash表中桶的数量;
初始化容量:创建hash表时桶的数量;
尺寸:当前hash表中记录的数量;
负载因子:负载因子等于0表示空的hash表,0.5表示半满的hash表,轻负载的hash表具有冲突少、适宜插入与查询等特点。
负载极限:负载极限是一个0~1之间的数值,决定了hash表的最大填满程度。当hash表的负载因子达到指定负载极限时,hash表会自动成倍地增加容量,并将原有的对象重新分配,放入新的桶中。HashSet、HashMap、Hashtable默认的负载极限是0.75。

8.TreeMap

保存了对象的排列次序

9.String、StringBuffer和StringBuilder

这三者都是表示字符串的
String:是引用类型,是不可变类(不可重新赋值,任何改变都会产生新的对象),其equals()方法被重写,比较的是其指向的字符串的asscii值是否相同,
StringBuffer:是线程安全的,相对于String在内容扩充时,不需要整体另外变换内存位置。而且没有重写equals()方法,其比较的还是引用地址。
StringBuilder:不支持线程安全,但是单线程性能更高
区别是:
1.首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String

/*
		 * String定义及初始化
		 * .split(),.concat(),.valueof();
		 */
		 //两种初始化的方法
		String str = "hello word";				//"hello word"存在了堆中,str作为引用存在了栈中
		String str_1 = "hello word";			//这里就不会另外申请空间,因为"hello word"已经在堆中存在,所以这里只是新建了一个引用指向了那个地址
		String str_2 = new String("hello word");//使用new一定是新建了一个对象,新分配了内存空间
		
		String [] arrayStr = str.split(" ");	//1用空格进对str及逆行分割,返回的是多个string类型
		for(String str1:arrayStr) {
			System.out.println(str1);
		}
		
		String str2 = "ni hao";
		String str3 = str.concat(str2);
		System.out.println(str3);
		
		String str4 = String.valueOf(100);		//1将括号中的int,double等站换成String
		System.out.println(str4);
		/*
		 * StringBuffer
		 * String
		 * StringBuilder.append(),.replace(),没有重写equals方法
		 * 和他们的substring(),.length(),初始化
		 */
		StringBuilder strBuilder = new StringBuilder("hello");		//1相比较StringBuffer线程安全
		StringBuffer sb = new StringBuffer("hello");
		sb.append(",world");		//1在sb后面连接上,world(改变的是sb而不是返回一个新的字符串)
		System.out.println("sb:" + sb);
		
		String str3 = sb.substring(2,6);	//1下标从0开始,截取2位到6位,包含开始索引(2)不包括结束索引(6)
		System.out.println("str3:" + str3);
		StringBuffer str4 = sb.replace(2, 6, "AAAAAA");	//1这里是讲str从2位到6位(不包括6),替换为后面的字符串(可以位数不相同)
		System.out.println("str4:" + str4);
		System.out.println("sb:" + sb);				//1针对StringBuffer的操作会改变其本身的值,而不是String那样不能改变其指向的字符串常量值

		//1练习:截取字符串后4位
		System.out.println("sb.length():" + sb.length());
		System.out.println(sb.substring(sb.length() - 4));		//1和下一行效果相同
//		System.out.println(sb.substring(sb.length() - 4, sb.length()));
		System.out.println("aaa.length():" + "aaa".length());
		
		//2练习:截取"Hello Java"的第2个到第4个字符串”
		String str5 = new String("Hello Java");
		String str6 = str5.substring(1,4);
		System.out.println("str6:" + str6);

三、基本函数

1.时间:Date和SimpleDateFormat和Calendar类

参考链接:
使用 Date 和 SimpleDateFormat 类表示时间
Calendar 类的应用
Date和Calender不支持时区,而且都不是线程安全。(SimpleDateFormat线程不安全,LocalDateTime线程安全参考链接
(1)Date()的使用
代码中的 “yyyy-MM-dd HH:mm:ss” 为预定义字符串, yyyy 表示四位年, MM 表示两位月份, dd 表示两位日期, HH 表示小时(使用24小时制), mm 表示分钟, ss 表示秒,这样就指定了转换的目标格式,最后调用 format() 方法将时间转换为指定的格式的字符串。
在这里插入图片描述运行结果: 2014-06-11 09:55:48

(2)使用parese()方法可以将文本转换为日期:
代码中的 “yyyy年MM月dd日 HH:mm:ss” 指定了字符串的日期格式,调用 parse() 方法将文本转换为日期。
在这里插入图片描述
(3)calendar类的使用
Calendar 类是一个抽象类,可以通过调用 getInstance() 静态方法获取一个 Calendar 对象,此对象已由当前日期时间初始化,即默认代表当前时间
在这里插入图片描述
(4)Date()碰到的一些转换

//①java.util.Date和java.sql.Date:
	//util.Date向sql.Date转换
	
	//sql.Date向util.Date不需要转换,因为sql.Date是util.Date的子集,

2.Math类操作数据

在这里插入图片描述

四、基本内容

1.包

参考链接:Java包管理的那些事1——IDE背后发生了什么
来源:有官方库也有个人库
依赖性:一个包A可能需要调用B才能正常实现功能,可能造成传递性依赖(解决方法为Maven)

2.反射

是通过实例化的类去找

获取Class对象信息:public final Class<?> getClass(); //date.getClass();能找到date所在的Class全名。
反射操作通过java.lang.Class实现的。(可以使用范型进行标记)
public final class Class extends Object implements Serializable,GenericDeclaration,Type,AnnotatedElement //Serializable可串行化,序列化
【Object类支持】public final Class<?> getClass(); //这种方式,必须实例化之后才能获得Class类对象
【JVM直接支持】采用“类.class”的形式实例化,这里必须导入类所在的包
【Class类支持】public static Class<?> forName(String className) throws ClassNotFound //直接用Class<?> cls = Class.Name(“类所在路径”); system.out.println(cls.getName());输出类的完整路径
可以直接采用字符串定义要使用的类型,并且不用import

反射实例化对象:
获取Class对象后,其中包括对象的实例化方法(代替了关键字new)。(这个方法还是要调用类中的无参构造方法,就跟new没什么区别)
JDK1.9之前:public T newInstance() throws InstantiationException(因为只能调用无参构造)
之后:clazz.getDeclaredConstructor().newInstance();(找的是构造方法的实例化)

Class<?> cls = Class.Name("类所在路径"); 
Object obj = cls.newInstance();	//实例化对象,会叫用构造函数(这里蕴含了  new 类名  的操作)
system.out.println(obj);		//输出对象时,调用toString方法

//1.9之后
Object obj = cls.getDeclaredConstructor().newInstance();

工厂模式设计来解决,客户端不直接牵扯到对象的实例化管理,只与接口发生关联,通过工厂类获取指定接口的实例化对象。(如果用对象当作接口的话,就会出现耦合问题——意思就是用实例化对象来实现存取数据的话,就会对对象类之间产生耦合问题,用工厂的话就只修改工厂类就行了,在里面进行判断,就是在多个方法或者说对象类(NetMessage,CloudMessage)中选择一个(IMessage)进行执行的时候,用工厂类进行判断,相对于在主函数中进行多层ifelse嵌套要好很多,)

参考链接:反射举例
静态工厂设计模式:但是每当多增加一个子类的时候,就要修改工厂类,子类多的时候,又会出现耦合问题
这里的Factory接受标志着NetMessage等子类的字符串参数,然后返回一个需要的类的对象
在这里插入图片描述
动态工厂设计模式(采用反射机制来代替,原来静态中的ifelse):
那么如果在工厂中用Class中的.Name()和.newInstance()来接收字符串路径或者类名称的字符串,再用newInstance来生成对象然后返回出去,就可以在工厂中不需要进行判断了,就降低了耦合问题,即新增加子类的时候不用修改工厂类了,也不会产生很长的ifelse。
在这里插入图片描述

适配所有接口的工厂模型(用范型来适配):

//工厂中的本来的判断类改为
public static <T> T getInstance(String className,Class<T> clazz){		//这里之所以加了一个Class<T>类型的参数是因为如果全都靠范型来判断的话开销大
	T instance = null;
	try{
		instance = (T) Class.forName(className).getDeclaredConstructor().newInstance(); 
	}catch(Exception e){
		e.printException();
	}
	return instance;
}

//主函数中调用方式:
	IMessage msg = Factory.getInstance("类的路径",IMessage.class);

3.单例设计模式

单例模式就是系统运行期间,有且只有一个实例。普通的,在多线程或是多个任务中会创建多个实例,但是对于数据库配置内容这种整个程序,只需要读取一次,可以被每个建立连接的类调用。
(1)一个类只有一个实例,是单例模式最基本的要求。
  要满足这个,只能提供私有的构造器(私有构造器不能被外部调用,所以在外部就没办法new)
(2)它必须自行创建这个实例。
  自行创建这个实例,去保证只有一个,那么需要定义static的JavaBean。
(3)它必须自行向系统提供这个实例。
  参考链接:Java基础之为什么在一个静态方法里调用非静态成员变量是非法的
  因为外面无法通过new去获取它的实例,所以提供一个静态的公有方法(因为构造器是私有(这里理解为静态,参考链接)的,所以此方法也必须是静态的),该方法创建或者获取(因为是static所以进行判断如果已经建立,就去获取)(懒汉模式和饿汉模式也会存在这种差异)它本身的静态私有对象,并返回。

所以进行总结,单例模式需要定义私有构造方法,在类内部进行实例化,然后用静态公有方法返回实例。

4.懒汉模式和饿汉模式

先清楚懒汉和饿汉的区别:
(1)懒汉模式:在类加载时不创建实例,采用延迟加载也就是在与运行调用时创建实例
具体实现:(参考3.单例)在定义JavaBean时,不进行实例化;在返回实例的静态公有方法中进行实例化。
特性:具备延迟加载,但是存在线程不安全的问题(因为如果多个线程同时调用返回实例的静态公有方法,就会实例化多个)。
(2)饿汉模式:在类加载的时候就实现实例化。
具体实现:(参考3.单例)在定义JavaBean时就进行实例化;在返回实例的静态公有方法中直接进行返回就行了
所以懒汉的类加载速度比饿汉快,但是获取对象的速度慢。如果说懒汉模式是“时间换空间”(延迟加载),那么饿汉模式是“空间换时间”。
(3)静态内部类:这个并不是模式,实现饿汉模式就有延迟加载的特性就可以综合两个的优点,实质上还是懒汉模式,因为时在调用的时候进行的实例化,参考饿汉式单例模式与静态内部类实现的懒汉式单例模式
java中的静态内部类有什么特点中匿名用户1级2015-06-24 回答的
跟饿汉比较而言,没有在加载类的时候就将对象初始化,而对比懒汉类,又使用内部静态类(原因如下)保证了只被实例化一次,避免了线程安全问题,或者避免了同步带来的性能问题。
//原因:虚拟机会保证一个类的构造器()方法在多线程环境中被正确地加载,同步,如果多个线程同时去初始化一个类,那么只有一个线程去执行这个类的构造器()方法,其他线程都需要阻塞等待,直到活动线程执行()方法完毕。
参考:静态内部类实现的单例模式是如何保证线程安全的

也就是说,让JavaBean在定义时不进行初始化,而是用一个静态内部类去包含new,这样在进行加载时,不会实例化,然后在调用方法时,不用进行判断而且又不会造成线程安全问题。

5.排序算法

十大经典排序算法

(1)选择排序

		/*
		 * 选择排序
		 */
		int[] intArray = new int[]{123,4,5,6343,34,3,434,3,3,4,7,7,89,54,43,3,676,7,23,3,3,45,6,7,178};	
		int temp = -1;
		for(int i=0;i<intArray.length-1;i++) {
			for(int j=i+1;j<intArray.length;j++) {
				if(intArray[i]>intArray[j]) {
					temp = intArray[i];
					intArray[i] = intArray[j];
					intArray[j] = temp;
				}
			}
		}
		
		System.out.println("最大值:" + intArray[intArray.length-1]);
		for(int i=0;i<intArray.length;i++) {
			System.out.println(intArray[i]);
		}
		if(intArray[intArray.length-1]%2 == 0) {
			System.out.println("是一个偶数");
		}else if(intArray[intArray.length-1]%2 == 1){
			System.out.println("是一个奇数");
		}else {
			System.out.println("奇偶数判断失败");
		}

(2)冒泡排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值