Android客户端面试所需基础

根据2015年的互联网公司笔试、面试经验,掌握这些东西的话!进大公司没问题。同时推荐牛客网,七月算法,赛码网(很多公司都是用的赛码网进行笔试)。分为以下几部分:
J2SE基础
1. 九种基本数据类型的大小,以及他们的封装类。
java中有八种基本数据类型,int ,double ,long ,float, short,byte,character,boolean;他们对应的封装类型是:Integer ,Double ,Long ,Float, Short,Byte,Character,Boolea;

2. Switch能否用string做参数?
在 Java 7之前,switch 只能支持 byte、short、char、int或者其对应的封装类以及 Enum 类型。在 Java 7中,String支持被加上了。

3. equals与==的区别。
        1、java中equals和==的区别 值类型是存储在内存中的堆栈(简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。
        2、==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。
        3、equals操作表示的两个变量是否是对同一个对象的引用,即堆中的内容是否相同。
        4、==比较的是2个对象的地址,而equals比较的是2个对象的内容,显然,当equals为true时,==不一定为true。

4. Object有哪些公用方法?
 Object是所有类的父类,任何类都默认继承Object。Object类到底实现了哪些方法?
1.clone方法
保护方法,实现对象的浅复制,只有实现了Cloneable接口才可以调用该方法,否则抛出CloneNotSupportedException异常。
2.getClass方法
final方法,获得运行时类型。
3.toString方法
该方法用得比较多,一般子类都有覆盖。
4.finalize方法
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
5.equals方法
该方法是非常重要的一个方法。一般equals和==是不一样的,但是在Object中两者是一样的。子类一般都要重写这个方法。
6.hashCode方法
该方法用于哈希查找,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
一般必须满足obj1.equals(obj2)==true。可以推出obj1.hash- Code()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。 
7.wait方法
wait方法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait()方法一直等待,直到获得锁或者被中断。wait(long timeout)设定一个超时间隔,如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
(1)其他线程调用了该对象的notify方法。
(2)其他线程调用了该对象的notifyAll方法。
(3)其他线程调用了interrupt中断该线程。
(4)时间间隔到了。
此时该线程就可以被调度了,如果是被中断的话就抛出一个InterruptedException异常。
8.notify方法
该方法唤醒在该对象上等待的某个线程。
9.notifyAll方法
该方法唤醒在该对象上等待的所有线程。

5. Java的四种引用,强弱软虚,用到的场景。
缓存系统引入弱引用或者软引用的唯一原因是,把引用clear的事情交由Java垃圾回收器来处理,cache程序自己置身事外。
强引用(StrongReference)
我们平时申明变量使用的就是强引用,普通系统99%以上都是强引用。比如,String s = "Hello World"
弱引用(WeakReference)
垃圾回收器某个时刻决定回收软可达的对象的时候,会清理软引用,并可选的把引用存放到一个引用队列(ReferenceQueue)。
软引用(SoftReference)
类似弱引用,只不过Java虚拟机会尽量让软引用的存活时间长一些,迫不得已才清理。
虚引用(PhantomReference)
仅用来处理资源的清理问题,比Object里面的finalize机制更灵活。get方法返回的永远是null,Java虚拟机不负责清理虚引用,但是它会把虚引用放到引用队列里面。

6. Hashcode的作用。
以java.lang.Object来理解,JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做Object的比较或者取这个对象的时候,它会根据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。具体过程是这样:
1.new Object(),JVM根据这个对象的Hashcode值,放入到对应的Hash表对应的Key上,如果不同的对象确产生了相同的hash值,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同hashcode的对象放到这个单链表上去,串在一起。
2.比较两个对象的时候,首先根据他们的hashcode去hash表中找他的对象,当两个对象的hashcode相同,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一定在这个key上的链表上。那么此时就只能根据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话,肯定他们不能equal.

7. ArrayList、LinkedList、Vector的区别。
LinkedList类
  LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
  注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
    List list = Collections.synchronizedList(new LinkedList(...));

ArrayList类
  ArrayList实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。
size,isEmpty,get,set方法运行时间为常数。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
  每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
  和LinkedList一样,ArrayList也是非同步的(unsynchronized)。

Vector类
  Vector非常类似ArrayList,但是Vector是同步的。由Vector创建的Iterator,虽然和ArrayList创建的Iterator是同一接口,但是,因为Vector是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector的状态(例如,添加或删除了一些元素),这时调用Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。

8. String、StringBuffer与StringBuilder的区别。
1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String
2.String <(StringBuffer,StringBuilder)的原因 : String:字符串常量   StringBuffer:字符串变量  StringBuilder:字符串变量
3、StringBuilder:线程非安全的 、 StringBuffer:线程安全的
4、对于三者使用的总结:
1.如果要操作少量的数据用 = String
2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder 
3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

9. Map、Set、List、Queue、Stack的特点与用法。
Map接口
Map集成Collection接口,Map和Collection是两种不同的集合,Collection是值(value)的集合,Map是键值对(key,value)的集合。包含几种主要类和接口:HashMap、LinkedMap、WeakHashMap、SortedMap、TreeMap、HashTable等几种。
  (1)Hashtable继承Map接口,实现一个key-value映射的哈希表。任何非空(non-null)的对象都可作为key或者value。添加数据使用put(key, value),取出数据使用get(key),这两个基本操作的时间开销为常数。
  (2)WeakHashMap类,WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,如果一个key不再被外部所引用,那么该key可以被GC回收。
Set接口
Set接口是继承自Collection的,它不能包含有重复元素。Set中最多有一个null元素。
因为Set的这个制约,在使用Set集合的时候,应该注意:
    1,为Set集合里的元素的实现类实现一个有效的equals(Object)方法。
    2,对Set的构造函数,传入的Collection参数不能包含重复的元素。
List接口
  List接口是有序的Collection,使用该接口能精确控制每个元素的插入位置,可以使用索引来访问List中的元素,跟数组是很类似的。并且List中允许有重复元素,当然有些List的实现类不允许重复元素的存在。
  List中有iterator()方法,还有listIterator方法,返回一个ListIterator接口,这个接口比标准的Iterator接口相比,多了一些add之类的方法,允许添加、删除、设置元素值以及向前或者向后遍历等。
Queue
    Queue用于模拟"队列"这种数据结构(先进先出 FIFO)。队列的头部保存着队列中存放时间最长的元素,队列的尾部保存着队列中存放时间最短的元素。新元素插入(offer)到队列的尾部,  访问元素(poll)操作会返回队列头部的元素,队列不允许随机访问队列中的元素。
Stack
Stack堆栈添加移除元素的原则是后进先出。 Stack类的主要方法是:push(),peek(),pop(),empty(),search().

10. HashMap和HashTable的区别。
HashMap和Hashtable都实现了Map接口,主要的区别有:线程安全性,同步(synchronization),以及速度。
1.HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
2.HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
3.另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
4.由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
5.HashMap不能保证随着时间的推移Map中的元素次序是不变的。

11. HashMap和ConcurrentHashMap的区别,HashMap的底层源码。
HashMap不是线程安全的,ConcurrentHashMap是线程安全的。
从ConcurrentHashMap代码中可以看出,它引入了一个“分段锁”的概念,具体可以理解为把一个大的Map拆分成N个小的HashTable,根据key.hashCode()来决定把key放到哪个HashTable中。
在ConcurrentHashMap中,就是把Map分成了N个Segment,put和get的时候,都是现根据key.hashCode()算出放到哪个Segment中

12. TreeMap、HashMap、LindedHashMap的区别。
Hashmap 是一个最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;
TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。
LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。

13. Collection包结构,与Collections的区别。
Collections是个java.util下的类,它包含有各种有关集合操作的静态方法。
Collection是个java.util下的接口,它是各种集合结构的父接口。

14. try catch finally,try里有return,finally还执行么?
1、不管有木有出现异常,finally块中代码都会执行;
2、当try和catch中有return时,finally仍然会执行;
3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

15. Excption与Error包结构。OOM你遇到过哪些情况,SOF你遇到过哪些情况。

16. Java面向对象的三个特征与含义。
封装性    
概念:它是将类的一些敏感信息隐藏在类的内部,不让外界直接访问到,但是可以通过getter/setter方法间接访问。
继承性  
概念:子类通过一种方式来接受父类所有的公有的,受保护的成员变量和成员方法。
多态性
概念:程序在运行的过程中,同一种类型在不同的条件下表现不同的结果,这种不定状态的表现形式,可以称为多态。

17. Override和Overload的含义去区别。
Overload:顾名思义,就是Over(重新)——load(加载),所以中文名称是重载。它可以表现类的多态性,可以是函数里面可以有相同的函数名但是参数名、返回值、类型不能相同;或者说可以改变参数、类型、返回值但是函数名字依然不变。
Override:就是ride(重写)的意思,在子类继承父类的时候子类中可以定义某方法与其父类有相同的名称和参数,当子类在调用这一函数时自动调用子类的方法,而父类相当于被覆盖(重写)了。

18. Interface与abstract类的区别。
1.抽象类可以有构造方法,接口中不能有构造方法。
2.抽象类中可以有普通成员变量,接口中没有普通成员变量
3.抽象类中可以包含非抽象的普通方法,接口中的所有方法必须都是抽象的,不能有非抽象的普通方法。
4. 抽象类中的抽象方法的访问类型可以是public,protected和(默认类型,虽然  eclipse下不报错,但应该也不行),但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。 
5. 抽象类中可以包含静态方法,接口中不能包含静态方法
6. 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
7. 一个类可以实现多个接口,但只能继承一个抽象类。

19. Static class 与non static class的区别。
1.首先是类中的数据,static的
class A {
static int a;
}
class B {
int b;
}
无论新建几个A对象,这几个对象公用一个int a,一个对象的a改变,另一个也会改变。
而B对象,不同对象之间的int b独立存在,互不影响,可以有多个值。

2.类中的方法
静态的方法,不需要建立对象就可以访问
如Math.abs()这个方法,我们没有建立Math的对象,就可以通过类名直接使用abs这个方法。
而非静态的方法,必须先建立对象,然后通过对象名,调用这个方法。
如JButton jb = new JButton();
    jb.addActionListener(l);

ps:在静态方法的定义中, 不能直接引用本类的其他非静态方法。例如。我们不能在main中直接引用,本类的其他方法。所以我们经常可以看见,在main方法中,先建立本类的一个对象,然后才通过对象调用本类的其他方法。

3.在初始化过程中,静态的总是先初始化。

20. java多态的实现原理。
◆强制的:一种隐式做类型转换的方法。
◆重载的:将一个标志符用作多个意义。
◆参数的:为不同类型的参数提供相同的操作。
◆包含的:类包含关系的抽象操作

21. 实现多线程的两种方法:Thread与Runable
1.通过继承Thread类构造线程。Java定义了一个直接从根类Object中派生的Thread类,所有从这个类派生的子类或者间接子类,均为线程;
2.实现一个Runable接口;

22. 线程同步的方法:sychronized、lock、reentrantLock等。
23. 锁的等级:方法锁、对象锁、类锁。
24. 写出生产者消费者模式。
25. ThreadLocal的设计理念与作用。
线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。
首先我们看一下ThreadLocal类的接口和设计思路。在J2SE5.0中,该类有1个默认构造函数,4个普通函数:protected ThreadLocal initialValue(),显然是为了子类重写而特意实现的。该方法返回当前线程在该线程局部变量的初始值,这个方法是一个延迟调用方法,在一个线程第1次调用get()或者set(Object)时才执行,并且仅执行1次;public ThreadLocal get(),返回当前线程的线程局部变量副本;public void set(ThreadLocal value),设置当前线程的线程局部变量副本的值;public void remove(),移除当前线程的线程局部变量副本的值以释放存储空间。 

26. ThreadPool用法与优势。
27. Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。
28. wait()和sleep()的区别。
共同点 :
1. 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。
2. wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。
不同点 :  
1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。
sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用
3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
4.sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
5.wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。

29. foreach与正常for循环效率对比。

30. Java IO与NIO。
31. 反射的作用于原理。
32. 泛型常用特点,List<String>能否转为List<Object>。
33. 解析XML的几种方式的原理与特点:DOM、SAX、PULL。
34. Java与C++对比。
35. Java1.7与1.8新特性。
36. 设计模式:单例、工厂、适配器、责任链、观察者等等。
37. JNI的使用。

推荐书籍:《java核心技术卷I》《Thinking in java》《java并发编程》《effictive java》《大话设计模式》


JVM

1. 内存模型以及分区,需要详细到每个区放什么。
2. 堆里面的分区:Eden,survival from to,老年代,各自的特点。
3. 对象创建方法,对象的内存分配,对象的访问定位。
4. GC的两种判定方法:引用计数与引用链。
5. GC的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?
6. GC收集器有哪些?CMS收集器与G1收集器的特点。
7. Minor GC与Full GC分别在什么时候发生?
8. 几种常用的内存调试工具:jmap、jstack、jconsole。
9. 类加载的五个过程:加载、验证、准备、解析、初始化。
10. 双亲委派模型:Bootstrap ClassLoader、Extension ClassLoader、ApplicationClassLoader。
11. 分派:静态分派与动态分派。
JVM过去过来就问了这么些问题,没怎么变,内存模型和GC算法这块问得比较多,可以在网上多找几篇博客来看看。
推荐书籍:《深入理解java虚拟机》


操作系统

1. 进程和线程的区别。
2. 死锁的必要条件,怎么处理死锁。
3. Window内存管理方式:段存储,页存储,段页存储。
4. 进程的几种状态。
5. IPC几种通信方式。
6. 什么是虚拟内存。
7. 虚拟地址、逻辑地址、线性地址、物理地址的区别。
因为是做android的这一块问得比较少一点,还有可能上我简历上没有写操作系统的原因。
推荐书籍:《深入理解现代操作系统》


TCP/IP
1. OSI与TCP/IP各层的结构与功能,都有哪些协议。
2. TCP与UDP的区别。
3. TCP报文结构。
4. TCP的三次握手与四次挥手过程,各个状态名称与含义,TIMEWAIT的作用。
5. TCP拥塞控制。
6. TCP滑动窗口与回退N针协议。
7. Http的报文结构。
8. Http的状态码含义。
9. Http request的几种类型。
10. Http1.1和Http1.0的区别
11. Http怎么处理长连接。
12. Cookie与Session的作用于原理。
13. 电脑上访问一个网页,整个过程是怎么样的:DNS、HTTP、TCP、OSPF、IP、ARP。
14. Ping的整个过程。ICMP报文是什么。
15. C/S模式下使用socket通信,几个关键函数。
16. IP地址分类。
17. 路由器与交换机区别。
网络其实大体分为两块,一个TCP协议,一个HTTP协议,只要把这两块以及相关协议搞清楚,一般问题不大。
推荐书籍:《TCP/IP协议族》


数据结构与算法

1. 链表与数组。
2. 队列和栈,出栈与入栈。
3. 链表的删除、插入、反向。
4. 字符串操作。
5. Hash表的hash函数,冲突解决方法有哪些。
6. 各种排序:冒泡、选择、插入、希尔、归并、快排、堆排、桶排、基数的原理、平均时间复杂度、最坏时间复杂度、空间复杂度、是否稳定。
7. 快排的partition函数与归并的Merge函数。
8. 对冒泡与快排的改进。
9. 二分查找,与变种二分查找。
10. 二叉树、B+树、AVL树、红黑树、哈夫曼树。
11. 二叉树的前中后续遍历:递归与非递归写法,层序遍历算法。
12. 图的BFS与DFS算法,最小生成树prim算法与最短路径Dijkstra算法。
13. KMP算法。
14. 排列组合问题。
15. 动态规划、贪心算法、分治算法。(一般不会问到)
16. 大数据处理:类似10亿条数据找出最大的1000个数.........等等
算法的话其实是个重点,因为最后都是要你写代码,所以算法还是需要花不少时间准备,这里有太多算法题,写不全,我的建议是没事多在OJ上刷刷题(牛客网、leetcode等),剑指offer上的算法要能理解并自己写出来,编程之美也推荐看一看。
推荐书籍:《大话数据结构》《剑指offer》《编程之美》


Android
1. Activity与Fragment的生命周期。

http://www.cnblogs.com/hibraincol/archive/2012/03/06/2382120.html
http://www.codeceo.com/article/android-fragment-life.html

2. Acitivty的四中启动模式与特点。
3. Activity缓存方法。
4. Service的生命周期,两种启动方法,有什么区别。
5. 怎么保证service不被杀死。
6. 广播的两种注册方法,有什么区别。
7. Intent的使用方法,可以传递哪些数据类型。
8. ContentProvider使用方法。
9. Thread、AsycTask、IntentService的使用场景与特点。
10. 五种布局: FrameLayout 、 LinearLayout 、 AbsoluteLayout 、 RelativeLayout 、 TableLayout 各自特点及绘制效率对比。
11. Android的数据存储形式。
12. Sqlite的基本操作。
13. Android中的MVC模式。
14. Merge、ViewStub的作用。
15. Json有什么优劣势。http://www.lingdublog.com/134.html
16. 动画有哪两类,各有什么特点?
17. Handler、Loop消息队列模型,各部分的作用。
18. 怎样退出终止App。  http://my.oschina.net/Bruce370/blog/536993
19. Asset目录与res目录的区别。
20. Android怎么加速启动Activity。
21. Android内存优化方法:ListView优化,及时关闭资源,图片缓存等等。
22. Android中弱引用与软引用的应用场景。http://blog.csdn.net/arui319/article/details/8489451  (to be continued)
23. Bitmap的四中属性,与每种属性队形的大小。
24. View与View Group分类。自定义View过程:onMeasure()、onLayout()、onDraw()。
25. Touch事件分发机制。
26. Android长连接,怎么处理心跳机制。
27. Zygote的启动过程。
28. Android IPC:Binder原理。http://my.oschina.net/Bruce370/blog/536946
29. 你用过什么框架,是否看过源码,是否知道底层原理。
30. Android5.0、6.0新特性。
Android的话,多是一些项目中的实践,使用多了,自然就知道了,还有就是多逛逛一些名人的博客,书上能讲到的东西不多。另外android底层的东西,有时间的话可以多了解一下,加分项。
推荐书籍:《疯狂android讲义》《深入理解android》


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值