java学习笔记 第二篇 核心技术(二)

第十四章 集合类

集合类用来存放对象的引用。继承关系如下图:

14.1 Collection 接口

是层次结构中的根接口,构成Collection的单位称为元素。Collection接口不能直接使用,但该接口提供了添加元素、删除元素、管理数据的方法。
Collection接口常用方法:

14.2 List 集合

包括List接口以及List集合的所有实现类。List集合中的元素允许重复,各元素循序就是对象插入的顺序

1.List接口,两个重要方法:

get(int index): 获取指定索引位置的元素
set(int index,Object obj): 将集合中指定索引位置的对象修改为指定的对象

2.List接口的实现类

ArrayList类实现可变数组,允许所以元素包括null,可快速随机访问
LinkedList采用链表结构保存对象。便于向集合中添加插入和删除对象
实例化List集合:
List list = new ArrayList();
List list2 = new LinkedList();

14.3 Set 集合

set集合中的对象不按特定方式排序,只是简单地把对象加入集合中,但不能包含重复对象。
常用的实现类:
HashSet,有哈希表支持。不保证set迭代顺序,不保证该顺序永恒不变。
TreeSet,集合按照自然顺序递增排序。

14.4 Map 集合

1.Map没有继承Collection接口,其提供的是key到value的映射
2.Map常用实现类:
HashMap。 //不保证映射的顺序,切顺序不保证永恒不变
TreeMap。 //j具有一定顺序,但在添加、删除和定位映射关系时,比HashMap性能差
可以通过HashMap类创建Map集合,当需要顺序输出时,再创建一个相同映射关系的TreeMap类实例
3.put(key k,valued v)方法中key与value 的类型都应是String型

第十五章 I/O输入输出

15.1 输入输出流

流是一组有序的数据序列,I/O流提供了一条通道程序,可以通过这条通道把源中的字节序列送到目的地。
输入输出流的类都放在java.io包中


15.2 File类

file类是唯一代表磁盘文件本身的对象

15.3文件输入输出流

15.3.1 FileInputStream与FileOutputStream类
15.3.2 FileReader类和FileWriter类

使用方法:

File file = new File("G:/word.txt");

char a[] = new char[1024];

FileReader reader= new FileReader(file);;

FileWriter fw = new FileWriter(file);

fw.write(a);
fw.close();

int len = reader.read(c);
System.out.println(new String(c,0,len));

reader.close();

15.4 带缓存的输入输出流

1.BufferedInputStream与BufferedOutputStream类
2.BufferedReader与BufferedWriter类

15.5 数据输入输出流

DataInputStream与DataOutputStream类

15.6 ZIP压缩输入输出流

zipInputStream与zipOutputStream

第十六章 反射

1.通过java反射机制,可以在程序中访问已经加载到JVM中的java对象的描述,
实现访问、检测和修改描述java对象本身信息的功能。由java.lang.reflect包提供功能支持。
2.所有java类继承了Object类,在object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。
例:Class textFieldC = textField.getClass(); //textField为JTextField类的对象
(以下反射部分引用自:http://w w w.360doc.com/content/10/1018/21/3236365_62059768.shtml)

◆16.1.Class类

Class类是Reflection API中的核心类,它有以下方法
(1)获得对象的类型:
getName():获得类的完整名字。
getFields():获得类的public类型的属性(成员变量)。
getDeclaredFields():获得类的所有属性。
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。
getMethod(String name, Class[] parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes参数指定方法的参数类型。
getConstrutors():获得类的public类型的构造方法。
getConstrutor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes参数指定构造方法的参数类型。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
(2)通过默认构造方法创建一个新的对象:
Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
(3)获得对象的所有属性:
Field fields[]=classType.getDeclaredFields();
 Class类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性。
以上代码先调用Class类的getConstructor()方法获得一个Constructor对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
(4)获得每个属性相应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性复制到新的对象中:
 for(int i=0; i  Field field=fields[i];  
String fieldName=field.getName(); 
 String firstLetter=fieldName.substring(0,1).toUpperCase(); 
 //获得和属性对应的getXXX()方法的名字  String getMethodName="get"+firstLetter+fieldName.substring(1);  
//获得和属性对应的setXXX()方法的名字  String setMethodName="set"+firstLetter+fieldName.substring(1);  
//获得和属性对应的getXXX()方法 
 Method getMethod=classType.getMethod(getMethodName,new Class[]{}); 
 //获得和属性对应的setXXX()方法 
 Method setMethod=classType.getMethod(setMethodName,new Class[]{field.getType()});  
//调用原对象的getXXX()方法  
Object value=getMethod.invoke(object,new Object[]{}); 
 System.out.println(fieldName+":"+value);  
//调用复制对象的setXXX()方法 
 setMethod.invoke(objectCopy,new Object[]{value});}

◆16.2.Method类(访问方法)

Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。
invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。

 ◆16.3.Array类

java.lang.Array类提供了动态创建和访问数组元素的各种静态方法。如例程10-4所示的ArrayTester1类的main()方法创建了一个长度为10的字符串数组,接着把索引位置为5的元素设为“hello”,然后再读取索引位置为5的元素的值。
import java.lang.reflect.*;
public class ArrayTester1 {
  public static void main(String args[])throws Exception {   
 Class classType = Class.forName("java.lang.String");   
//创建一个长度为10的字符串数组  
  Object array = Array.newInstance(classType, 10);   
 //把索引位置为5的元素设为"hello"  
  Array.set(array, 5, "hello");   
//读取索引位置为5的元素的值   
String s = (String) Array.get(array, 5);    System.out.println(s);  }}
(关与运用反射操作数组详情,转:http://blog.csdn.net/hqs_1992/article/details/24046875)

◆16.4.Annotation类型

1.Annotation功能可用于类、构造方法、成员变量、方法、参数等的声明中。该功能不影响程序运行,但会对编辑器的警告等辅助工具产生影响。
2.定义Annotation类型,也需要用到用来定义接口的interface关键字,不过需要在interface关键字前加一个“@”符号。这个关键字隐含意思是继承了java.lang.annotation.Annotation接口。
定义实例:
public @interface DefaoltValueAnnotation{
String describe() default "<默认值>";//定义成员变量时,可以为成员变量设置默认值。
Class type() default void.class;//成员类型可以是String、Class、primitive、enumerated和annotation,以及所列类型的数组
}
3.可通过@Target来设置Annotation类型所适用的程序元素种类。枚举类ElementType中的枚举常量用来设置@Targer。
例:@Target(ElementType.TYPE)
4.通过@Retention可设置Annotation的有效范围。枚举类RetentionPollicy中的枚举常量用来设置@Retention。
例:@Retention(RetentionPollicy.RUNTIME)

16.4.2访问Annotation信息

1.如果定义Annotation类型时将@Retention设置为RetentionPollicy.RUNTIME,那么运行程序时可通过反射获取相关Annotation信息。
2.类Consturctor、Field和Method均继承AccessibleObject类,在AccessibleObject中定义了3个关于Annotation的方法:
方法isAnnotationPresent(Class<? extends Annotation>annotationClass)用来查看是否添加了指定类型的Annotation,是返回true,否则返回false;
方法getAnnotation(Class<I>annotationClass)用来获取指定类型的Annotation,存在则返回相应的对象,否则返回null;
方法getAnnotation()用来获取所以Annotation,该方法返回一个Annotation数组。

第十七章 枚举类型与泛型

17.1 枚举类型

1.在程序设计中,有时会用到由若干个有限数据元素组成的集合,如一周内的星期一到星期日七个数据元素组成的集合,由三种颜色红、黄、绿组成的集合,一个工作班组内十个职工组成的集合等等,程序中某个变量取值仅限于集合中的元素。此时,可将这些数据集合定义为枚举类型。因此,枚举类型是某类数据可能取值的集合,如一周内星期可能取值的集合为:
  { Sun,Mon,Tue,Wed,Thu,Fri,Sat}
  该集合可定义为描述星期的枚举类型,该枚举类型共有七个元素,因而用枚举类型定义的枚举变量只能取集合中的某一元素值。由于枚举类型是导出数据类型,因此,必须先定义枚举类型,然后再用枚举类型定义枚举型变量。

2.语法: 

  enum <枚举类型名> 
  { <枚举元素表> };
  其中:关键词enum表示定义的是枚举类型,枚举类型名由标识符组成,而枚举元素表由枚举元素或枚举常量组成。例如: 
  enum weekdays 
  { Sun,Mon,Tue,Wed,Thu,Fri,Sat };

3.用户可以将一个枚举类型看作一个类(但需在类内定义!)它继承于java.lang.Enum类,当定义一个枚举类型时,每一个枚举类型成员都可以看作是枚举类型的一个实例,这些枚举类型成员默认都被final、public、static所修饰,所以当使用枚举成员时直接使用枚举类型名称调用枚举类型成员即可。

4.枚举类型常用方法:

values(),将枚举类型的成员变量实例以数组的形式返回,也可通过该方法获取枚举类型的成员。

valueOf(),可以将普通字符串转换为枚举类型。

compareTo(),用于比较两个枚举类型对象定义时的顺序。

ordinal(),获取某个枚举对象的位置索引值。

5.在枚举类型中,可以添加构造方法,但是构造方法必须为private修饰符所修饰。

17.2 泛型

1.泛型其实就像一个口袋,你可以很方便地往里面装东西,只是在第一次使用这个口袋的时候要注意声明它只能装什么样类型的东西,以后就不能装错了。那么我们就用钱包为例吧,我们首先描述一下钱包。钱包的用途不外乎是装点儿东西,当然,除了钱还可以装其它很多东西,例如银行卡、便签条、照片等等,但是这些东西有些共同的地方,至少是尺寸方面不能超过钱包的限制,谁可以把冰箱也揣在钱包里呢?因此,我们在设计能装进钱包的物品的类的时候就要考虑到尺寸的因素。
2. 定义泛型类: 类名<T> //T代表一个类型名称
定义泛型类时,一般讲类型名称使用T来表达,二容器元素使用E来表达。
3. 定义泛型类时可以声明多个类型 :MutiOverClass<T1,T2>
声明数组类型:public class ArrayClass<T>{private T[] array;}//定义泛型数组
集合类声明容器的元素:可以使用K和V两个字符代表容器中的键值和与键值相对应的具体值。
public class MutiOverClass<K,V>{public Map<K,V> m = new HashMap<K,V>();}//定义一个集合HashMap实例
4.常用的被泛型化的集合类:ArrayList<E>;HashMap<K,V>;HashSet<E>;Vector<E>
5.限制泛型可用类型:class 类名称<T extends anyClass> //anyClass是指某个类或接口
6.使用类型通配符:泛型类名称<? extends List> a=null; //<? extends List>表示类型未知,当需要使用该泛型对象时,可以单独实例化
如果使用A<?>这种形式实例化泛型类对象,则默认表示可以使用A指定为实例化Object及以下的子类类型。
7.定义为泛型的类和接口也可以被继承与实现

第十八章 多线程

1.           世间万物都可以同时完成多项工作,这种思想放在Java中被称为并发,而将并发完成的每一件事情称为线程。程序员在Java程序中可以执h行多个线程,每个线程完成一个功能,并与其他线程并发执行,这种机制称为多线程。

2.       进程:每个进程是一个包含有自身地址的程序,每个立执行的程序都称为进程,也就是正在执行的程序。


3.一个线程是进程中的执行流程,一个进程中可以同时包括多个线程,每个线程可以得到一小段程序的执行时间,这样一个进程就可以具有多个并发执行的线程。

18.1 实现线程的两种方式

1.继承Thread类

1.Thread类是Java.lang包中的一个类,从这个类中实例化的对象代表线程,程序员启动一个新线程需要建立Thread实例。

2.Thread类中常用的构造方法:publicThread([String threadName])  //StringthreadName线程名称

3.完成线程真正功能的代码放在类的run()方法中,而Thread类中start()方法执h行线程,也就是调用run()方法。主方法线程启动由Java虚拟机负责,程序员负责启动自己的线程。

2. 实现Runnable接口

1.如果程序员需要继承其他类(非Thread类),而且还要是当前类实现多线程,由于Java不支持多继承,就只能通过Runnable接口实现。(实质上

Thread类就是实现了Runnable接口)

2.语法:publicclass Thread extends Object implements Runnable

3.实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象相关联。Thread类中有以下构造方法:

         public Thread(Runnable r,[String name]) //此构造方法可以将Runnable实例与Thread实例相关联。

4.使用Runnable接口启动新线程的步骤:

         建立Runnable对象;

         使用参数为Runnable对象的构造方法创建Thread实例;

         调用start()方法启动线程。

实例:

  1. package mythread;  
  2.  
  3. public class MyRunnable implements Runnable  
  4. {  
  5.     public void run()  
  6.     {  
  7.         System.out.println(Thread.currentThread().getName());  
  8.     }  
  9.     public static void main(String[] args)  
  10.     {  
  11.         MyRunnable t1 = new MyRunnable();  
  12.         MyRunnable t2 = new MyRunnable();  
  13.         Thread thread1 = new Thread(t1, "MyThread1");  
  14.         Thread thread2 = new Thread(t2);  
  15.         thread2.setName("MyThread2");  
  16.         thread1.start();  
  17.         thread2.start();  
  18.     }  
  19. }  

18.2 线程的生命周期

线程包含7中状态:出生状态、就绪状态、运行状态、等待状态、休眠状态、阻塞状态和死亡状态。

18.3 操作线程的方法

1.线程的休眠(sleep())

sleep()方法需要一个参数用于指定该线程休眠的时间,以毫秒为单位

语法:Thread.sleep(2000);

2.线程的加入(join())

在A线程中插入B线程。当某个线程使用join()加入到另一个线程时,另一个线程会等待该线程研究完毕后再继续执行。

3.线程的中断(stop())

当前不建议使用stop()方法,提h倡在run()方法中使用无限循环的形式,然后使用一个布尔型标价控制循环的停止。

18.4 线程的优先级

Thread类中包含的成员变量代表了线程的某些优先级,如Thread.MIN_PRIORITY(常数1)、Thread.MAX_PRIORITY(常数10)、Thread.NORM_PRIORITY(常数5)【默认】

线程的优先级可以使用setPriority方法调整

18.5 线程同步

线程同步机*^制为了解决资源共享时,发生多个线程同一时间共享一个资源的情况。采用给定时间只允许一个线程访问共享,给共享资源上一道锁。

同步机hh制使用synchronized关键字。

1.同步块语法:

synchronized(Object){   语句   }

2.同步方法语法:

synchronized voidf(){ }

第十九章 网络通信

19.1  网络程序设计基础

1.网络程序设计是指编写与其他计算机进行通信的程序。

2.网路协议,规定了计算机之间连接的物理、机械(网卡与网线的连接规定)、电气(有效地电平范围)等特征及计算机之间的相互寻址规则、数据发送冲突的解决,长的数据如何分段传送与接收等。

3.TCP/IP协议栈中,有两个高级协议:“传输控制协议”(TCP)与“用户数据报协议”(UDP)

4.TCP协议以固接连线为基础的协议,数据传送可靠。.UDP是无连接通信协议,不保证可靠的数据传输。

5.一般一台计算机只有单一的连到网络的“物理连接”,这就是端口。网络程序设计中的端口(Port)并非真实的物理存在,而是假象的连接装置。端口被规定为一个在0~65535之间的整数。HTTP服务一般使用80端口。FTP服务使用21端口。

6.通常0~1023之间的端口数用于一些知名的网络服务和应用,用户的普通网络应用程序应该使用1024以上的端口数,避免冲突。

7.网络程序中套接字(socket)用于将应用程序与端口连接起来。套接字是一个假想的连接装置,就像插座,用来连接电器与电线。Java将套接字抽象化为类--Socket类。

Socket类的常用方法:

[java]  view plain copy
  1. public Socket(InetAddress address,int port) throws IOException  
  2. public Socket(String host,int port) throws UnknowHostException,IOException  
  3. public Socket(InetAddress address,int port,InetAddress localAddr,int localport) throws IOException  
  4.   
  5. public InetAddress getInetAddress()//返回套接字连接的主机地址  
  6. public InetAddress getLocalAddress()//返回套接字绑定的本地地址  
  7. public InputStream getInputStream()throws IOException//获得该套接字的输入流  
  8. public int getLocalPort()//返回套接字绑定的本地端口  
  9. public int getPort()//返回套接字连接的远程端口  
  10. public OutputStream getOutputSteam()throws IOException//返回该套接字的输出流  
  11. public int getSoTimeout()throws SocketException//返回该套接字最长等待时间  
  12.   
  13.   
  14. public void setSoTimeout(int timeout)throws SocketException//设置该套接字最长等待时间  
  15.   
  16. public void shutdownInput()throws IOException//关闭输入流  
  17. public void shutdownOutput()throws IOException//关闭输出流  
  18.   
  19. public void close()throws IOException//关闭套接字  

19.2 TCP程序设计基础

19.2.1 InetAddress类

位于java.net包中,该类可获取IP地址、主机地址等信息。

常用方法有:

getByName(String host) //获取与Host相对应的InetAddress对象

getHostAddress() //获取InetAddress对象所含的IP地址

getHostName() //获取此IP地址的主机名

getLocalHost() //返回本地主机的InetAddress对象

19.2.2 ServerSocket类

位于java.net包中,用于表示服务器套接字,主要功能是等待来自网络上的“请求”,它可通过指定的端口来等待连接的套接字。服务器套接字一次可以与一个套接字连接。多台客户机同时提出连接请求时,服务器套接字会将请求连接的的客户机存入列队中。若请求连接数大于最大容纳数(默认50),则多出的请求会拒绝。
构造方法:
ServerSocket([int port],[int backlog],[InetAddress bindAddress]) //使用指定的端口、侦听backlog和要绑定到的本地IP地址创建服务器。
ServerSocket常用方法:
  1. public ServerSocket(int port) throws IOException  
  2. public ServerSocket(int port,int backlog) throws IOException  
  3. public ServerSocket(int port,int backlog,InetAddress bindAddr) throws IOException  
  4.   
  5.   
  6. public Socket accept() throws IOException//监听并接受客户端Socket连接  
  7. public InetAddress getInetAddress()//返回服务器套接字的本地地址  
  8.   
  9. public int getLocalPort()//返回套接字监听的端口  
  10.   
  11.   
  12.   
  13. public int getSoTimeout()throws SocketException//返回该套接字最长等待时间  
  14.   
  15.   
  16. public void setSoTimeout(int timeout)throws SocketException//设置该套接字最长等待时间     
  17.   
  18. public void close()throws IOException//关闭套接字  

19.2.3 TCP网络程序

19.3 UDP程序设计基础

UDP程序的步骤:

1.发送数据包
a.使用DatagramSocket()创建一个数据包套接字
b.使用DatagramPacket(byte[] buf,int offset,int length,InetAddress address,int port)创建要发送的数据包
c.使用DatagramSocket类的send()方法发送数据包
2.接受数据包

a.使用DatagramSocket(int port)创建数据包套接字,绑定到指定的端口

b.使用DatagramPacket(byte[] buf,int length)创建字节数组来接收数据包。

c.使用DatagramPacket类的receive()方法接收UDP包。

DatagramPacket类

位于java.net包,用来表示数据包
构造函数:DatagramPacket(byte[] buf,int length,[InetAddress],[int pot])

DatagramSocket类

位于java.net包中,用于发送和接收数据包的套接字。
构造函数:DatagramSocket([int port],[InteAddress addr])

补充:

详细网络编程可查看:h t t p://www.bianceng.cn/Programming/Java/201003/16146.htm

第二十章 数据库操作

1.数据库系统是由数据库、数据库管理系统和应用系统、数据库管理员构成。数据库管理系统简称DBMS,是数据库系统的关键组成部分,包括数据库定义、数据查询、数据维护等。
2.数据库指的是以一定方式储存在一起、能为多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合
3.SQL(结构化查询语言),可以方便的查询、操作、定义和控制数据库中的数据。

20.1 SQL语言主要部分组成:

1.数据定义语言(DDL),如create、alter 、drop等
2.数据操纵语言(DML),如select、insert、update、delete等
3.数据控制语言(DCL),如grant、revoke等
4.事务控制语言,如commit、rollback等

常用数据操纵语言:

1.select语句
数据表中检索数据
语法:
SELECT  所选字段列表 FROM 数据表名
WHERE 条件表达式 GROUP BY 字段名 HAVING 条件表达式(指定分组的条件)
ORDER BY 字段名[ASC|DESC]
例子:select name,age from tb_emp where sex = '女' order by age;
2.insert语句
向表中插入新数据
语法:
insert into 表名[(字段名 1,字段名 2,···)]
values(属性值 1,属性值 2,···)
例子:insert into tb_emp values(2,‘lili’,‘女’,‘销售部’);
3.update语句
用于更新数据表中某些记录
语法:
UPDATE 数据表名 SET 字段名 = 新的字段值 WHERE 条件表达式
例子:update tb_emp set age = 24 where id = 2;
4.delete语句
用于删除数据
语法:
delete from 数据表名 where 条件表达式
例子:delete from tb_emp where id = 1024;

20.2 JDBC

1.JDBC技术

JDBC是一种可用于执行SQL语句的Java API,是连接数据库和Java应用程序的纽带。
JDBC技术主要完成以下几个任务:
1.与数据库建立一个连接
2.向数据库发送SQL语句
3.处理从数据库返回的结果
JDBC不能直接访问数据库,必须依赖于数据库厂商提供的JDBC驱动程序。

2.JDBC驱动类型

1)JDBC-ODBC桥


 把标准的JDBC调用转换成相应的ODBC调用,并通过ODBC库把它们发送给ODBC数据源。这种方式访问数据库,需要经过多层调用,效率比较低。访问Micros Access数据库,就只能通过这种方式来访问。



 
 
 2)部分本地API Java驱动程序


 利用JDBC API访问数据库时,JDBC驱动程序将调用请求转换为数据库厂商提供的本地API调用,数据库处理完请求将结果通过这些API返回,进而返回给JDBC驱动程序,JDBC驱动程序将结果转化为JDBC标准形式,再返回客户程序。
 这种类型减少了ODBC的调用环节,极高了数据库访问的效率,并且能够充分利用厂商提供的本地API的功能。
 

 
 3)JDBC网络纯Java驱动程序(首先)


 这种驱动利用应用服务器作为中间件来访问数据库。应用服务器作为一个到多个数据库的网关,客户端通过它可以连接到不同的数据服务器。应用服务器都有自己的网络协议,Java客户程序通过JDBC驱动程序将JDBC调用发送给应用服务器,应用服务器使用本地驱动程序访问数据库,从而完成请求。
 

 
 4)本地协议的纯Java驱动程序(首先)


 客户程序通过网络直接与数据库进行通信。数据库访问效率最高。



3. JDBC常用的类和接口

1.Connection接口
代表与特定的数据库的连接,在连接上下文中执行SQL语句并返回结果。
2.Statement接口
用于在已经创立连接的基础上向数据库发送SQL语句
3.PreparedStatement接口
用来动态的执行SQL语句
4.DriverManager类
用来管理数据库中的所有驱动程序。
5.ResultSet接口
类似于一个临时表,用来暂时存放数据库查询操作所获取的结果集。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值