当前位置:   article > 正文

java高级_java attributevalue

java attributevalue

java高级

反射

一.定义

在 Java 中语言之所以会有如此众多的支持,很大一部分来自 Java 最大的特征反射机制

反射之中所有的核心操作都是通过 Class 类对象展开的,Class 类是反射操作的根源所在,但是这个类如果要想获取它的实例化对象,可以采用三种方式完成

1.[ Object 类支持]

Object 类可以根据实例化对象获取 Class 对象: public final Class <?> getClass()

缺点:如果现在只想获得 Class 类对象,则必须产生指定类对象后才可以获得
在这里插入图片描述

2.[ JVM 直接支持]

采用“类 .class '的形式实例化

特点:如果要采用此种模式,则必须导入程序所对应的开发包

在这里插入图片描述

3.[ Class 类支持]

在 Class 类里面提供有一个 static 方法:

public static Class <?> forName ( String className )
throws ClassNotFoundExceptio
  • 1
  • 2

在这里插入图片描述

这种模式最大的特点是可以直接采用字符串的形式定义要使用的类型,并且程序中不需要编写任何的 import 语句。要使用的程序类不存在则会抛出 “ java . lang . ClassNotFoundException ” 异常。

反射实例化对象

获取 Class 对象之后最大的意义实际上并不是在于只是一个对象的实例化操作形式,更重要的是 Class 类里面提供的反射实例化方法(代替了关键字 new )

在 JDK 1.9以前的实例化:

newInstance();
  • 1

JDK 1.9 之后:class .getDeclaredConstructor().newInstance();

现在通过反射实现的对象实例化处理,依然要调用类中的无参构造方法

其本质等价于“类对象= new 类()”,也就是说当于隐含了关键字 new ,而直接使用字符串进行了替代。

范例:从 JDK1.9 之后 newInstance ()被替代了

因为默认的 Class 类中的 newInstance ()方法只能够调用无参构造,所以很多开发者会认为其描述的不准确,于是将其变换了

在这里插入图片描述

在这里插入图片描述

反射工厂设计模式:

package test1;

import java.lang.reflect.InvocationTargetException;

interface IMessage{
	public void send();
}
interface Service{
	public void service();
}
class HouseService implements Service{
	public void service(){
		System.out.println("宾馆服务");
	}
}
class SendMessage implements IMessage{
	public void send() {
		System.out.println("发送消息");
	}
}
class Factory{
	private Factory() {};
	/*
	 * 获取接口实例化对象
	 * classname 接口的子类
	 * clazz 描述一个接口的类型
	 * 如果子类存在则返还接口实例化对象
	 */
    @SuppressWarnings("unchecked")
	public static <T> T getinstance(String classname,Class<T> clazz){
    	T instance =null;
    	try {
			instance =(T)Class.forName(classname).getDeclaredConstructor().newInstance();
		} catch (Exception e) {
			e.printStackTrace();
		} 
    	return instance;
    }
}
public class main{
    public static void main(String args[]){
    	IMessage msg=Factory.getinstance("test1.SendMessage", IMessage.class);
    	msg.send();
    	Service ser=Factory.getinstance("test1.HouseService",Service.class);
    	ser.service();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

反射与类操作

反射调用构造方法

获取所有构造方法:

public Constructor <?>[] getDeclaredConstructors ()
throwsSecurityException
  • 1
  • 2

获取指定构造方法:

public Constructor < T > getDeclaredConstructor ( Class <?>...parameterTypes ) 
throws NoSuchMethodException ,SecurityException
  • 1
  • 2

获取所有构造方法:

public Constructor <?>[]getConstructors ()
throws SecurityException
  • 1
  • 2

获取指定构造方法:

public Constructor < T > getConstructor ( Class <?>.. parameterTypes ) 
throws NoSuchMethodException ,Security Exception
  • 1
  • 2

在这里插入图片描述

反射调用普通方法

\1. 获取全部方法(包括父类);

public Method[] getMethods()throws SecurityException
  • 1

\2. 获取指定方法;

public Method getMethod(String name,
Class<?>... parameterTypes)
throws NoSuchMethodException,SecurityException
  • 1
  • 2
  • 3

\3. 获取本类全部方法;

public Method[] getDeclaredMethods()
 throws SecurityException
  • 1
  • 2

\4. 获取本类指定方法;

public Method getDeclaredMethod(String name,
Class<?>.. parameterTypes)
Throws NoSuchMethodException,
SecurityException
  • 1
  • 2
  • 3
  • 4

范例:在不导入指定类开发包的情况下实现属性的配置

所以代码需要按照如下思考

1.任何情况下,如果要想保存类中的属性或者调用类中的方法,都必须保证存在有实例化对象,居然不允许导入包,那么就反射实例化。

2.如果要想进行方法的调用,那么一定要获取方法的名称。Attribute 是 string 类型,用于获取指定的方法。Setname 为方法名称。Invoke 要传递参数,接收实例化对象。

//obj为反射获取的实例化类对象
String setMethodName = "setName“//方法名
Method setMethod= cls-getDeclaredMethod(setMethodName,String-class)// 期所E的方法
setMethod.invoke(obj,value)String getMethodName = "getName";
Method getMethod = cls.getDeclaredMethod(getMethodName)System.out.print1n(getMethod.invoke(obj));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

反射与简单java类

当一个简单java类有很多个属性时,实现属性赋值需要反复调用多个setter方法,当java类多的时候,此时设置属性的工作就会十分烦锁,此时可以设计一个反射工厂类,由该工厂来实现属性的自动设置。

1.需要通过反射进行指定类对象的实例化

2.进行内容的设置(Field属性类型,方法名称,要设置的内容)

在这里插入图片描述

\1. 定义 stringutils 实现首字母大写功能

class StringUtils {
public static String initcap(String str){
	 if(str ==null ||"".equals(str)){
		return str ;
	}
	if (str.length()== 1)return str.toupperCase();
	 else {
		return str.substring(0,1).toupperCase() + str.substring(1);
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2.定义 beanutils 工具类,该工具类主要实现属性的设置

//obj:要进行放射操作的实例化对象
//包含有属性内容的字符串 	`String value="empno:7369|ename:132|dept.company.name:ddd|dept.dname:财务"`
class Beanutils{
        public static void setValue(Object obj,String value){
       			 String results []= value.split("\\|"//通过|进行 拆分
            forint x= 0;x<results.length;x++{   //循环设置属性内容
                String attva1[]=retu1ts[×].split(“:”); //获取属性名称与内容
                    try{
                  if(attval[0].contains(".")){ //多级配置
                      String temp[]=attval[0].split("//.");
                      Object currentObject=obj;
                      for(int y=0,y<temp.length-1;y++){ //实例化
                          //调用getter方法,如果返回null,则该对象未实例化
                     Method getMethod=obj.getClass().getDeclaredField("get"+StringUtils.initcap(temp[y]));
                     Object tempObjict=getMethod.invoke(currentObject)//此处实例化对象是可变的
                          if(tempObjict==null){ //该对象未实例化
                    Field field=currentObject.getClass().getDeclaredField(temp[y])//获取属性类型
Method method=currentObject.getClass().getDeclaredField("set"+StringUtils.initcap(temp[y]),field.getType());
                              method.invoke(currentObject,field.getType().getConstructor.newInstance());
                              currentObject=field.getType().getDeclaredConstructor.newInstance();
                          }
                          else {currentObject=tempObject;}
                      }
                 Field field = obj.getClass().getDeclaredField(temp[temp.length-1]);   
    MethodsetMethod=obj.getclass().getDeclaredMethod("set"+Stringutils.initcap(temp[temp.length-1]),filed.getType())Object val=Beanutils.convertAttributeValue(field.getType().getname(),attval[1]);
        
                 setMethod.invoke(obj,val);       //调用方法    
             }      
           else {     Field field = currentObject.getClass().getDeclaredField(attval[0]);// 获取成员
   	MethodsetMethod=currentObject.getclass().getDeclaredMethod("set"+Stringutils.initcap(attval[0]),filed.getType())//获取方法
        		Object val=Beanutils.convertAttributeValue(field.getType().getname(),attval[1]);
        
                 setMethod.invoke(obj,val);       //调用方法                                     
                    }
                catch (Exception e){}
               }
            }
    	}
        //实现属性类型转换处理  tpye:属性类型,通过field获取  value:属性内容,初始为字符串,需要转换为type类型
        private static Object convertAttributeValue(String type ,String value){
            if("long".equals(type)||"java.lang.long".equals(type))reutrn Long.parseLong(value);
             if("int".equals(type)||"java.lang.int".equals(type))reutrn Int.parseInt(value);
             if("double".equals(type)||"java.lang.double".equals(type))reutrn Double.parseDouble(value);
            if("java.util.Date".equal(type)){
                SimpleDateFormat sdf=null;
                if(value.matches("//d{4}-//d{2}-//d{2}")){
                    sdf=new SimpleDateFormat("yyyy-MM-dd")
                }
                else return new Date();
                try{
                    return sdf.parse(value);
                }catch(){}
            }
        }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

首先按照数线进行每一组属性的拆分,其次循环设置属性内容,attval[Θ] 保存的是属性名称,attval[1] 保存的是属性内容,然后获取属性名称与内容,获取成员,接下来调用 setter 方法设置内容。

Classinstancefactory 负责实例化对象并调用 beanutils 实现属性内容的设置

class ClassInstanceFactory {
private ClassInstanceFactory(){}
public static <T> T create(Class<?> clazz,String value){
tryObject obj = clazz.getDeclaredConstructor().newInstance();
    	BeanUtils.setVolue(obj,value); //通过反射,进行属性赋值
		returnT)obj;
) catch (Exception e) {  
	e.printStackTrace()}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

级联关系时:

在这里插入图片描述

反射与代理设计模式

动态代理模式:

在这里插入图片描述

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class test {

    public static void main(String arg[]) {
        IMessage msg = (IMessage) new MLDNProxy().bind(new MessageReal());
        msg.send();
    }

}
class MLDNProxy implements InvocationHandler{
    private Object target;
    //进行真实业务对象与代理对象的绑定
    public Object bind(Object target){
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
    public Boolean connect(){
        System.out.println("[通道]");
        return true;
    }
    public Boolean close(){
        System.out.println("[关闭通道]");
        return true;
    }
//    /**
//
//     * 代理方法调用,代理主题类里面执行的方法最终都是此方法
//
//     * @param proxy要代理的对象
//
//     * @param method要执行的接口方法名称
//
//     * @param args 传递的参数
//
//     * @return 某一个方法的返回值
//
//     * @throws Throwable 方法调用时出现的错误继续向上抛出
//
//     */

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("[invoke]");
        Object returnDate=null;
        if(this.connect()){
            returnDate=method.invoke(this.target,args);
            this.close();
        }
        return returnDate;
    }
}
interface IMessage{
    public void send();
}
class MessageReal implements IMessage{

    @Override
    public void send() {
        System.out.println("[发送信息]");
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
CBLIG代理设计模式:

基于类的代理设计模式,是第三方程序包,需要自己配置安装第三方开发包

class Message{
    public void send(){
        System.out.println("fason");
    }
}
class MLDNProxy implements MethodInterceptor{
    private Object target;
    //进行真实业务对象与代理对象的绑定
    public MLDNProxy(Object target){
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
    public Boolean connect(){
        System.out.println("[通道]");
        return true;
    }
    public Boolean close(){
        System.out.println("[关闭通道]");
        return true;
    }
    
      public Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {
        Object returnDate=null;
        if(this.connect()){
            returnDate=method.invoke(this.target,args);
            this.close();
        }
        return returnDate;
    }
}

public class test {

    public static void main(String arg[]) {
       Message msg=new Message();
        Enhancer enhancer=new Enhancer();//负责代理操作的程序类
        enhancer.setSuperclass(msg.getClass())//假定一个父类
        enhancer.setCallback(new MLDNProxy(msg)) //设置代理类
        Messgae proxymessage=(Message)enhancer.create();
        proxymessage.send();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

反射与Annotation

Annotation:注解信息

import java.io.Serializable;
import java.lang.annotation.Annotation;
public class test {

    public static void main(String arg[]) {
        //获取接口上的所有Annotation信息
        Annotation annotation[]=IMessage.class.getAnnotations();
        for(Annotation temp:annotation){
            System.out.println(temp);
        }

    }

}
@FunctionalInterface
interface IMessage{
    public void send(String msg);
}

@SuppressWarnings("serial")
class MessageReal implements IMessage, Serializable {

    @Override
    public void send(String msg) {
        System.out.println("[发送信息]"+msg);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

自定义Annotation

使用@interface注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
public class test {

    public static void main(String arg[]) throws Exception {
        Method method=Imessage.class.getMethod("send",String.class);//获取指定方法
        DefaultAnnotation an=method.getAnnotation(DefaultAnnotation.class);//获取指定Annotation
        String msg= an.title()   +  an.url();//消息内容
        method.invoke(Imessage.class.getDeclaredConstructor().newInstance(),msg);

    }

}
@Retention(RetentionPolicy.RUNTIME)//定义运行策略
@interface DefaultAnnotation{  //自定义
    public String title();
    public  String url() default "123";
}
class Imessage {
    @DefaultAnnotation(title = "123")
    public void send(String msg){
        System.out.println(msg);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

工厂设计模式与Annotation整合

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//当改变代理对象时,只需要修改MessgaeMain上的注解值即可
public class test {
    public static void main(String arg[]) throws Exception {
        MessgaeMain me=new MessgaeMain();
        me.send("123");
    }
}
@Retention(RetentionPolicy.RUNTIME)//定义运行策略
@interface DefaultAnnotation{  //自定义
    public Class<?> clazz();
}
@DefaultAnnotation(clazz = realmsg.class) //利用Annotation实现类的使用
class MessgaeMain{
    private IMessage message;
    public MessgaeMain() throws Exception {
        DefaultAnnotation an=MessgaeMain.class.getAnnotation(DefaultAnnotation.class);

        this.message= (IMessage) Factory.getInstance(an.clazz());
    }
    public void send(String msg){
        this.message.send(msg);
    }
}
class Factory{
    private Factory(){}
    public static <T> T getInstance(Class<T> clazz) throws Exception {//返回实例化操作对象
        return (T)new MessageProxy().banding(clazz.getDeclaredConstructor().newInstance());
    }
}
class MessageProxy implements InvocationHandler{
    private Object target;
    public Object banding(Object target){
        this.target=target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(this.target,args);
    }
}
interface IMessage{
    public void send(String msg);
}
class realmsg implements IMessage{
    @Override
    public void send(String msg) {
        System.out.println(msg);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

Map

HashMap

package cn.mldn. demo;
import java.util.HashMap;
import java.util.Map;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
Map<String, Integer> map = new HashMap<String,Integer>()
map.put ( "one",1) ;
map.put( "two",2) ;
map.put( "one",101) ;``//``key重复map.put( nu11, ) ; 
//``key为nul``l
map.put( "zero", null) ; ``//``value为null
system.out.print1n(map.get( "one" ) );``//``key存在
system.out.print1n(map.get(null));``//`` key存在
system.out.println(map.get(ten));``//``key不存在
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

以上的操作形式为 Map 集合使用的最标准的处理形式,通过代码可以发现,通过HashMap 实例化的 Map 接口可以针对 key 或 value 保存 null 的数据,

同时也可以发现即便保存数据的 kev 重复,那么也不会出现错误,而是出现内容的替换。

但是对于 Map 接口中提供的 put() 方法本身是提供有返回值的,那么返回值指的是在重复 key 的情况下返回旧得 value。

在设置了相同的 key 的内容的时候 put() 方法会返回原始的数据内容

面试题:在进行 HashMap 的put() 操作的时候,如何实现容量扩充的?

在 HashMap 类里面提供有一个 “DEFAULT_INITIAL_CAPACITY” 常量,作为初始化的容量配置,而后这个常量的默认大小为 16 个元素,也就是说默认可以保存的最大内容是 16;

当保存的内容的容量超过了与个阈值(DEFAULT_LOAD_FACTOR = 0.75f), 相当于“容量*阈值=12”保存 12 个元素的时候就会进行容量的扩充;

在进行扩充的时候HashMap 采用的是成倍的扩充模式,即:每一次都扩充 ⒉倍容量

当hashmap的存储量小于阈值8时,内部使用链表存储。当存储量大于8时,改用红黑树左右旋存储以保证查询数据的效率

Hashtable

在 Hashtable 里面进行数据存储的时候设置的 kev 或 value 都不允许为 null,否则会出现 NullPointerException 异常。

面试题:HashMap与Hashtable的区别

​ HashMap中的方法都属于异步操作(非线程安全),允许保存null数据

​ Hashtable中的方法属于同步操作(线程安全),不允许保存null数据

LinkedHashMap

HashMap 虽然是 Map 集合最为常用的一个子类,但是其本身所保存的数据都是无序的(有序与否对 Map 没有影响),如果现在希望 Map 集合之中保存的数据的顺序为其增加顺序,则就可以更换子类为 LinkedHashMap(基于链表实现的)。

观察 LinkedHashMap 类的的定义形式:

public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
  • 1
  • 2
  • 3

既然是链表保存,所以一般在使用 LinkedHashMap 类的时候往往数据量都不要特别大,因为会造成时间复杂度攀升。

Iterator遍历Map

如果要想使用 Iterator 实现 Map 集合的输出则必须按照如下步骤处理:

利用 Map 接口中提供的 entrySet() 方法将 Map 集合转为 Set集合

利用 Set 接口中的 iterator() 方法将 Set 集合转为 Iterator 接口实例

利用 Iterator 进行迭代输出获取每一组的 Map.Entry 对象,随后通过 getKey() 与getValue() 获取数据。

import java.util.HashMap;
import java.util.Iterator;
import java.uti1.Map;
import java.uti1.set;
public class JavaAPIDemo {
	public static void main(String[ ] args ) throws Exception {
		Map<string,Integer> map = new HashMap<StringInteger>();
		map.put( "one", 1);
		map.put( "two",2);
		Set<Map.Entry<String,Integer>> set = map.entrySet() ; //将Map集合变为Set集合								Iterator<Map.Entry<String,Integer>> iter = set.iterator( ) ;
		while (iter.hasNext()) {
			Map.Entry<String, Integer> me = iter.next() ;
			system.out.print1n(me.getKey() + " = " + me.getValue());
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

自定义Map的key类型

对于自定义 Key 类型所在的类中一定要覆写 hashCode() 与 equals() 方法,否则无法查找到。
在这里插入图片描述

面试题:如果在进行 HashMap 进行数据操作的时候出现了 Hash 冲突( Hash 码相同),HashMap 是如何解决的?

当出现了 Hash 冲突之后为了保证程序的正常执行,会在冲突的位置上将所有 Hash 冲突的内容转为链表保存。

List

ArraryList

通过过有参构造方法可以发现,在 ArrayI ist 里而所包含的数据实际上就是一个对象数组,如果现在在进行数据追加的时候发现 ArrayList 集合里面保存的对象数组的长度不够的时候那么会进行新的数组开辟,同时将原始的旧数组内容拷贝到新数组,这个数组的开辟操作:

如果在实例化 ArrayList 类对象的时候并没有传递初始化的长度,则默认情况下会使用一个空数但是如果在使用数据增加的时候发现数组容量不够了。

则会判断当前的增长的容量与默认的容量的大小,使用较大的一个数值进行,就可以得出一个结论:

JDK1.9 之后: ArrayI ist 默认的构造只会使用默认的空数组,使用的时候才会开辟数组,默认的开辟长度为 10

JDK1.9 之前: ArrayL ist 默认的构造实际上就会默认开辟大小为 10 的数组。

当 ArrayList 之中保存的容量不足的时候会采用成倍的方式进行增长,原始长度为10 , 那么下次的增长就是 20 ,以此类推,估算出数据量会有多少,如果超过了 10 个,那么使用有参构造方法进行创建,以避免垃圾数组的产生。

在使用 List 保存自定义类对象的时候如果需要使用到 containsO 、remove0 方法进行查询与删除处理时候,一定要保证之中已经成功的覆写了 equalsQ 方法

LinkedList

链表实现

面试题:清向 Array ist 与 LinkedList 有什幺区別? .

ArrayList 是数组实现的集合操作,而 LinkedList 是延表突现的集合操作: .

在使用 List 集合中的 get()方法根据索引获取数据时,ArrayList 的时间复杂度“O(l)”、而 Link 的时间长度为O(n)(n为集合的长度)

ArrayI ist 在使用的时候默认的初始化对象数组的大小长.应 10 ,数组的大小长度为 10, 如果空间不足则会采用2倍的形式进行容量的扩充,如果保存大数据量的时候有可能会造成垃圾的产生以及性能的下降,但是这个时候可以使用 LinkedList 子类保存。

Vector

Vector 类如果使用的是无参构造方法,则一定会默认开辟一个 10 个长度的数组,而后面其余的实现操作与 ArrayList 是相同的。通过源代码的分析可以发现 Vector类之中的操作方法采用的都是 synchronized 同步处理,而 ArrayList 并没有进行同步处理,所以 Vector 类之中的方法在多线程访问安全得,但是性能不如 ArrayList高。

Set

HashSet

不允许保存重复元素( Set 接口定义的),另外一点 HashSet 之中保存的数据是无序的

TreeSet

当利用 TreeSet 保存的数据的时候所有的数据都将按照数据的升序进行自动排序处理。

TreeSet 本质是利用 TreeMap 子类实现的集合数据的存储,而 TreeMap 就需要根据 Comparable 来确定大小好关系。

在使用自定义类对象进行比较处理的时候一定要将该类之中的所有属性都依次进行大小关系的匹配,否则如果某一个或某几个属性相同的时候它也会认为是重复数据,所以 TreeSet 是利用了 Comparable 接口来确认重复数据的。

由于 TreeSet 在操作过程之中需要将类中的所有属性进行比对,这样的实现难度太高了,那么在实际的开发之中应该首选 HashSet 子类进行存储

集合工具类

Stack

先进后出

要了解栈的继承结构,先得找到 Vector 类的继承结构,在整个的操作里面,Stack 是一个操作子类,继承自 Vector 这个父类。

在这里插入图片描述

虽然栈这个结构,在现在开发中所写的情况比较少,但是栈这个数据结构依然是个重要的结构,是开发之中必不可少的操作。

Queue

基本的操作形式:Queue 有两个端点。一端是队尾,一端是队头或队首,所有的操作数据都是通过队首一个一个的往里输入,这是队列的一个操作的本质,在实际的处理操作过程之中,有两个操作形式。

向我们的队列之中追加数据:public boolean offer(E e)可以直接用 add()方法;

通过我们的队列获取数据:public E poll(),弹出后删除数据。

优先队列:PriortyQueue 实现优先级队列(比较功能)。

有排序操作的,一定跟 Comparable 接口有直接的对应关系,只有接口之后才好确定优先级的设置问题。

这叫做优先级队列的操作处理,在开发过程中可以选用 Queue也可以选用

Properties

java.util 包里面提供有 Properties 类型,此类是 Hashtable 的子类。

public class Properties extends Hashtable .
  • 1

1、可以发现在继承 Hashtable 的时候为 Hashtable 中定义的泛型为 Object, Properties 是不需要操作泛型的,因为它能操作的类型只能是 String 类型。

在 Properties 之中如果想要实现属性的操作可以采用如下的方法:

① 设置属性:setProperty(String key, String value)

② 取得属性:getProperty(String key),如果没有指定的key则返回null

③ 取得属性:getProperty(String key, String defaultValue),如果没有指定的 key 则返回默认值

④ 获得属性列表:list(PrintStream out)

⑤ 存为文件:store(OutputStream out,String comment)

⑥ 读取资源文件: load(InputStream in)

最大特点:

使用 properties 外形的最大的特点是可以进行资源内容的输入与输出处理操作,但是在实际的开发之中,Properties 往往用于读取配置资源的信息,这一点主要是在标准设计之中做程序初始化准备的时候使用

Collections工具类

是 Java 提供的一组集合数据的操作工具类,利用它可以实现各个集合的操作。

1.Collections操作List集合

https://ucc.alicdn.com/pic/developer-ecology/0df0efd873e84913a3eca790785dd71a.png

2.数据翻转

在这里插入图片描述

3.二分

在这里插入图片描述

要先进行排序

注:大部分情况下的使用没有太多复杂要求,更多情况就是利用集合保存数据去进行输出或查询

5.面试题:

请解释 Collection 与 Collections 的区别:

Collection 是集合接口,允许保存单值对象。

Collections 是集合操作的工具类。

Stream数据流

Stream 主要功能是进行数据的分析处理,同时主要是针对于集合中的数据进行分析操作。

count操作:选出含有字母J的元素

在这里插入图片描述

将满足条件的元素存到新list集合中:

在这里插入图片描述

设置取出的最大数据量:public Stream<T>limit(long maxSize);

·跳过指定数据量:public Stream<T>skip(long n)。

分页:
在这里插入图片描述

在进行数据分析的处理之中有一个最重要的基础模型:MapReduce 模型,对于这个模型一共是分为两个部分:Map 处理部分,Reduce 分析部分,在进行数据分析之前必须要对数据进行合理的处理,而后才可以做统计分析操作。
在这里插入图片描述

DoubleSummaryStatistics stat= all.stream().filter((ele)->ele.getName().contains(“强”)).mapToDouble((orderObject.getPrice()*orderObject,getAmount()).summaryStatistics();

JDBC链接Oracle

一定要保证已经成功的启动了 Oracle 数据库的两个服务:数据监听服务、(listene)实例服务(SID)。

在管理当中我们找到服务,在服务里面我们能够找到监听,其中有两幅,oracleoradb11g_home1TnNSlListenner 以及 oracleservicemldm 这两副要手动启动,如果不启动,程序则无法使用上,但是需要注意的是,这两副启动完后也并不是可以直接连接了。

由于本次将直接利用 JDBC 进行 oracle 数据库的连接,所以必须保证你的系统之中已经配置了 oracle 的驱动程序,驱动程序的配置分两种情况

情况一

如果你现在使用了记事本进行程序编写,则需要将其手工配置到 classpath 之中,比如说我们找到一个操作跟上一个环境,这么这个地方有一个 classpath ,第二个就是我们的程序路径,这个程序在我们安装目录之中,找到我们 oracle 之中的安装程序包,这个地方是有它的程序路径的,我们找到 6 ,它就是我们的驱动程序路径,

oracle 驱动程序路径:D:\app\mldn\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar; 那么就要在系统中将路径配置到 classpath 之中,这样才能在本机命令行方式进行编写,但是这种方式对于 lips 是无效的,所以需要第二种情况。

情况二

基于 Eclipse 开发,所以需要在 JavaBuilderPath 上配置此驱动程序,我们找到Eclipse,将属性,buildpath,classpath,加入扩展架,把代码放进去就可以完成了

然后将路径复制过来,正常开发情况下,建议我们用第二种做法,用 class 配置非常复杂,我们现在一个包,但是可能以后会有上百个包,用 class 下来就非常麻烦,

如果现在要连接 Oracle 数据库,则必须采用如下的步骤进行处理

1、保证情况正常的情况下,通过反射机制加载数据库驱动程序类**:**Oracle JDBC 程序下有一个 Oracle driver,是驱动程序,通过反射机制加载数据库驱动程序类: Oracle.jdbc.driver.oracledriver

2、数据库的连接需要有一个网络的连接地址,该地址结构如下,地址结构**:**jdbc:Oracle:thin:@主机名称:端口号:SID。

MLDN 数据库:jdbc:Oracle:thin:@localhost:1521:mldn 也可以直接写 IP 地址,这就是数据库的连接地址,static final sting 跟上database,找到 UR,但是只靠连接地址不行,我们还需要数据库的用户名:Scott 数据库的密码:tiger 问题是连接怎么做。

对于数据库的连接,提供有 java.sql.drivermanager 的数据类,利用此类中的方法可以获取一个 connection 的接口对象。

3、获取 connection 的接口对象,找到 drivermanager,用此方法直接跟上连接对象,接入地址,用户以及密码。

范例:实现具体的数据库连接操作,找到 connectionConn 表,每一个 connection的接口对象描述的就是一个用户连接,那么 Conn 就等于 drivermanager.getco,数据库的连接资源有限一定要关闭,这样就实现了一个数据库的连接处理,实验验证即可。

(如果此时在输出 connection 的接口对象的时候并没有任何的异常,那么就表示当前的 Oracle 数据库已经可以正常的连接了。)

但是这个时候肯定都在思考一个问题:

为什么要连接 Oracle 数据库的时候一定要单独配置数据库的驱动程序呢?

首先 JDBC 是一个操作标准,既然是标准,那么就证明里面是不牵扯到具体实现类,有数据库厂商来实现,下面将以上连接的过程通过类图的关系来进行描述,首先我们见到接口,将它取来,这个接口名字为 connection,每一个用户就是connection,这个 connection 一定允许实现自动关闭处理,我们跟上 autocloseable,在这个操作处理的时候,这个 connection 的连接对象被drivermanager 所获得,那 drivermanager 需要操作三项支持,分别是连接地址,用户名,密码。

多线程:

实现方式:

1.继承Thread类

覆写run方法为进程主方法,多线程要执行的功能要应该在run方法中定义,run不能直接调用,而应该使用start方法

2.实现Runnable接口

覆写run方法,因为启动多线程必须调用MyThread类中的start方法,所以实现接口启动多线程需要:

Thread 对象名=new Thread(new 实现了接口的类名(线程对象名称))

可以直接使用Lambda表达式定义。(使用Runnable无法获取一个返回值)

3.实现Callable接口

Callable定义时可以设置一个泛型(返回数值的类型 )

在这里插入图片描述

线程休眠:Thread.sleep()
线程中断:Thread.interrupt()
线程强制执行:线程名.join()
线程礼让:Thread.yiled()
线程优先级:

设置优先级:public final void setPriority(int new Priority)

同步操作:使用synchronized关键字 会造成性能的降低
线程等待::public final void wait() throws InterruptException;如果需要设置时间,则传入参数
线程唤醒:public final void notify() --唤醒第一个线程,public final void notifyAll() --唤醒全部线程
volatile:(表面同步)正常数据操作是先拷贝一个副本,然后在进行操作,然后在赋值给原空间,而使用volatile则直接操作原地址空 间,不进行副本操作。
String,StringBuffer和,StringBuilder。

String是字符串的首选类,特点内容是不可修改(在每次改变时,都相当于新建了一个新的string对象,把指针指向新对象)

后俩者可以修改内容 StringBuffer线程安全,Build不安全

正则表达式

方便验证处理,以及方便进行复杂字符串的修改处理

创建匹配字符串,:

String regex=

1.=字符,字符匹配(单个),字符串是否一样

2.=[abc],表示可能是a,b,c中的任意一个

3.=[ ^ abc ],表示不是a,b,c中的任意一个

4.[a-zA-Z],表示任意字母组成,不区分大小写

5.【0-9】任意数字组成

6.“.”,任意字符

7.\d :任意数字

8.\D:不是数字

9\s :匹配任意一个空格,可能是空格,换行,制表符

10.\S :配置非空格

  1. \w:匹配字母,数字,下划线

  2. 表达式?:该正则可以出现0-1次

  3. 表达式*:出现任意次

  4. 表达式+:一次或多次

  5. 表达式{n}:表达式长度正好为n

  6. 表达式{n,}:表达式长度n以上

  7. 表达式{n,m}:长度n-m之间

字符串正则方法:在这里插入图片描述

java.util.regex包的应用(用于复杂操作)(此处为取出jdbc数据中的数据“deptno,dname,loc”)

replaceAll替换为("#|\{|\}")
在这里插入图片描述

UUID:在对文件进行自自动命名处理的时候使用

生成无重复字符串的程序类

获取uuid对象:public static UUID randomUUID();

Optional类:进行空的相关处理

获取数据(不许为空):public T get();

保存数据,不许为null:public static Optional of(T value)

保存数据,可以null:public static Optional ofNullable(T value)

为空的时候返回括号内的数据:public T orElse(T other)

使用时:例如:public static Optional< message > optional()

ThreadLocal类

多线程使用时,可能会出现数据覆盖,这时,使用此类解决

这个类有俩个数据区,一个用来记录当前线程对象,一个用来存数据,当取值时,对应线程取得对应数据,避免数据覆盖问题

有set(),get(),remove()方法

使用时:例如:public static ThreadLocal < message > threadlocal =new ThreadLocal< message >() 其中,message为对象

定时器:实现间隔触发操作

java.util.TimerTask类:实现任务处理(抽象类)

java.util.Timer类:进行任务的启动,启动的方法;

​ *任务启动:public void schedule(TimerTask task,long delay) 延迟delay毫秒后执行

​ *间隔触发:public void scheduleAtFixedRate(TimerTask task,long delay,long period) delay毫秒后执行,每period毫秒执行一次

Base64加密工具类

为保证加密,一般执行多次加密,加盐值。加密次数跟盐值由自己定义

Base64.Encoder: 进行加密处理

Base64.Decoder:进行解密处理

比较器(自定义类排序)

确定大小关系的判断

Comparable< T >接口:制定比较规则

复写compareto方法

Comparator比较器接口:起初只有compare方法,后续又发展了许多static方法

刚开始没有实现排序功能,后期需要排序却不能修改源代码,此时的挽救方法

新建一个排序类,为原类进行排序

运用:Arrays.sort(原类,排序类)

红黑树

本质上是一种二叉查找树,但它在二叉树的基础上额外添加了一个标记(颜色),同时具有一定规则,保证插入,删除,查找的最坏时间都为o(logn)

1.每个节点要么是黑色,要么是红色

2.根节点必须是黑色

3.每个叶子节点是黑色;(java使用的红黑树使用null来代表空节点,因此遍历红黑树时看不到黑色的叶子节点,而都是红色的)

3.如果一个节点是红色的,那么它的子节点必须为黑色

​ 从每个跟到节点的路径上不会有俩个连续的红色节点,但是黑色节点可以连续。若给定黑色节点的个数N,最短路径情况是连续的N个 黑色节点,树的高度为N-1;最长路径的情况为节点红黑相同,树的高度为2(N-1)

4.从一个节点到该节点的子孙节点的所有路劲上包含相同数目的黑节点数量

文件操作

简单略

File为保证在不同系统下的文件路径问题(不同系统的文件分隔符不同),定义了separator变量来代替分隔符

当父目录不存在情况出现时,首先调用public File getParentFile()方法加上public boolean exists()来判断父路径是否存在

如果不存在,可以调用public boolean mkdir(s)()来创建目录

public boolean isDirectory() 判断是否是目录

public boolean isFile() 判断是否是文件

public []File listFiles();列出目录下的所有文件

IO

字节输出流OutputStream
方法名称类型
public abstract void Write(int b)普通输出单个字节数据
public void Write(byte[] b)普通输出一组字节数据
public void Write(byte[] b,int off,int len)普通输出部分字节数据

使用FileOutputSteam向上转型得到outputstream对象(构造函数接收File类对象),如果是文件追加写入,在new FileOutputStream构造中加入true参数,

文本中使用/r/n换行

注意要关闭资源

字节输入流InputStream
方法名称类型
public abstract int read(int b)普通读取单个字节数据,返回字节数据
public int read(byte[] b)普通读取一组字节数据,返回长度
public int read(byte[] b,int off,int len)普通读取部分字节数据,返回真实长度

如果已经读取到底,返回-1

使用FileInputtSteam向上转型得到Inputstream对象(构造函数接收File类对象)

字符输出流Writer

输出字符数组:public void write(char[] a)

输出字符串:public void write(String a)

追加字符串:public void append(String a)

字符输入流Reader

读取字符数组:public int read(char[] a)

转换流

OutputStreamWriter 继承writer,构造方法接收outputstream

InputStreamReader 继承reader,构造方法接收inputstream

打印流:以后文件写入操作统一使用

PrintStream:

Public PrintStream(OutputStream out)

PrintWriter:强于前者

Public PrintWriter(OutputStream out)

Public PrintWriter(Writer writer)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/802883
推荐阅读
相关标签
  

闽ICP备14008679号