十三、内部类
内部类,就是定义在类中的类。这种机制老实说还没在实际开发中用到~~
所谓嵌套类,就是static的内部类。当然它就不能访问外围对象了。这一系列遇到了再总结到一起。嵌套类,可以用作测试
接口也可以有内部类。
内部类吸引人的原因:内部类可以单独继承一些接口,这种方式可以完善“多继承”(多实现)。感觉好像没什么用,whatever,遇到再看看。有一种情况,比如接口是在抽象类中,这种方式确实有用哦!这个就像是直线和斜线走路一样,一个速度快点,一个可以欣赏风景,看心情选择怎么走。
闭包(closure),这个概念又不记得了,应该就是说一个作用域问题,内部类被创建了,就自动拥有指向创建它的外围对象的引用。这个概念对实现回调(callback)很有用。感觉就像,老师教你去他办公室,默认就知道是谁叫的你。
内部类在继承了接口之后,可以利用权限访问控制符限制访问。内部类还有很多怪怪的用法,比如定义在方法中的、匿名内部类。匿名内部类,很有意思,也就是出了这个类,根本找不到这个实现。就像拾金不昧,连名字都没记下来,根本找不到原来的那个人。
内部类如果访问外部的参数,要求必须是final。如果是方法传的形式参数,而且传给构造方法就不用是final的。
十四、集合类(Collection)
Arrays.asList() 转换成List
对于集合类,有个迭代器的概念。
为什么要有迭代器?因为对于不同的集合类(List,Set)可以赋予相同的操作。迭代器统一了对容器的访问方式。Iterator单向移动,LinkedList双向移动。
ArrayList的查找效率高,LinkedList在中间的插入效率较高。
HashSet的查找顺序较高,因为它采用了散列表方式。
十五、异常
Throwable的子类:Error(用于Java虚拟机报告系统错误)、Exception和RuntimeException。Error用来表示编译时错误和系统错误(除特殊情况外,一般不关心),Exception是被抛出的基本类型,通常关注的是Exception。而RuntimeException是运行时异常,不需要声明(就是不用写throws) ,也被称为不受检查异常。
十六、字符串
1,编译器中的+
String对象是不可变的,看起来修改String的方法,实际上都是创建了全新的String对象。因此,对String用"+"来进行操作时,会产生一大堆对象(最初,后来编译器采用了StringBuilder)。
String s = "abc" + "132" + "def";
比如上面这一句,编译器创建了一个StringBuilder对象,用以构建最终的String。可以通过反编译来查看这个过程。最终而言,如果有循环,显示地调用StringBuilder更高效(没有显示调用,会在每个循环中生成一个StringBuilder)。
如果拿不准的时候,可以用javap 来分析。
javap -c className
2,无意识递归
这种方式可能造成无意识的递归:
toString() {
return "address : " + this.toString();
}
应该用+super.toString()
3,格式化
printf,java也有格式化输出
System.out.format也是格式化输出,和printf类似或者说等价
Formmater类
String.format()
Scanner,标准化
1.字符串类
final类,无法继承
2.内部采用char[]数组存储
3.length()方法
返回的字符的个数。
4.字符串内部不能改变,属于常量。(有个常亮池的概念)
字符集
--------------------
ascii :美国国家标准交换码,使用一个字节的7位表示。
iso-8859-1 :欧洲码表,使用8位表示,无法存储汉字。
gb2312 :中文码表,简体中文.两个字节存储。
gbk :gb2312升级版
big-5 :繁体中文,
utf-8 :变长字符表示法,最多使用3个字节表示。
unicode :两个字节表示字符,java中使用该码表。
编码
------------
encode
String --> byte[]
Sring.getBytes("");
解码
------------
decode
byte[] --> String
com.it18zhang.java11.test.TestString2
gbk
----------
97 //a
98 //b
99 //c
-42, -48//中
-71, -6 //国
utf-8
----------
97, 98, 99,
-28, -72, -83 //中
-27, -101, -67 //国
StringBuffer
------------------
线程安全的。
StringBuilder
-------------------
不是线程安全的。一般用StringBuilder
html
------------
String
十七、类型信息
1,类是如何加载的?
运行时类型信息使得你可以在程序运行时发现和使用类型信息。类型信息在运行时如何表示,这项工作是由称为Class对象的特殊对象完成的。每个类都有个Class类,相当于每编译一个类就会生成一个Class对象,生成这个对象的子系统叫“类加载器”。
这个子系统可以包含一条加载器链,但是只有一个原生加载器,它是JVM实现的一部分。
所有类都是第一次使用时,动态加载到JVM中。
类加载器先检查这个类的Class对象是否已经加载,没加载时,先去找.class,然后验证没有被破坏,且不包含不良Java代码。static语句就是在类加载过程中运行的。
Class.forName("xxx")是取得class对象引用的一种方法,调用它是为了加载xxx类。
Class.getInterface返回的也是Class对象,说明Class对象包含接口。
对于基本类型对应的包装类还有一个对应关系:比如boolean.class等价于 Boolean.TYPE,还有一个有趣的对象void.class,等价于Void.class。
还有有趣的一点:当使用.class类创建对象时,不会自动初始化该类对象。为了使用类而做了三项工作:
(1)加载,即找到字节码,然后创建一个Class对象;(2)链接,验证字节码,为静态域分配存储空间;(3)初始化,即调用构造方法,以此生成对象。
2,泛型
就像这种格式Class<Integer> ,就是泛型。泛型实现了参数化类型的概念,但是与其他语言相比,没有那么优雅。
将java与C++中的泛型进行比较,有两个原因:一是C++的模板有助于理解泛型基础;二是可以了解Java泛型的局限,以及为什么会出现这些限制。最终的目的是帮助你理解,Java泛型的边界在哪里。根据我的经验,理解了边界所在,你才能成为程序高手。因为你只有知道了技术不能做什么,你才能更好地做到所能做到的。
Java泛型的核心概念就是告诉编译器你想使用什么类型。利用泛型可以实现元组的概念,所谓元组(Tuple),就是将一组对象存储于其中的一个单一对象,这个容器对象允许读取其中的元素,但是不允许向其中存放新的对象。比如TwoTuple<A,B>,而A和B用final修饰。
泛型方法:public <T> void f(T x)
Class<?>则是通配,?表示任何事物。?也可以继承:Class<? extends ***>。
为何要给Class添加泛型?就是为了在编译期内提供检查。
有一个关键字instanceof,是否是某个类型的实例。而isInstance方法提供一种动态测试对象的途径。
残酷的一点是,在泛型代码内部,无法获取任何有关泛型参数类型的信息。比如List<String>和List<Integer>两个被视作是一样的。这种擦除的方式,降低了泛型的有用性。擦除的核心动机是使得泛化的类可以用非泛化的类库来使用,反之亦然,这经常被称为“迁移兼容性”。为了兼容Java1.5和之前的代码,因此选择了这种方式。
3,反射
所谓反射,就是在运行时获取类型信息,而且反射可以获取对象的全部信息,但是有一个东东它是改不了的,就是final。
十八、集合类
1,集合介绍
Iterable <|-- Collection <| -- List
|----- <| -- Set
ArrayList
--------------
写慢,读快(指定下标)。
数组列表
Object[]
Capacity //容量
size //元素的个数
index + offset
List判断对象是否存在,只跟equals有关。
LinkedList
---------------
写快,读慢。
可重复。
Vector
---------------
类似于ArrayList,通过Object[]实现。
线程安全的。
Set
----------------
元素是唯一的,不重复
无序的。
HashSet和hashMap没有本质区别。
hashSet通过hashmap实现的。
Key<Key,dummy>
和List、Set相对的一个体系是Map,他们是并行关系
Map
----------------
映射.
Key ---> value //Entry,条目
put(k,v); //1.判断hashcode相同,在判断是否同一对象,如果是同一对象,再判断equals方法
putValue
(e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
这个HashMap的存储结构有两层:
(1)Node<K,V>[] tab;
(2)Node<K,V>
结合这个图来看,显示根据hash值来放,如果有重复的,就通过链表来链接,Node<K,V>有下一个节点的地址。
hash的来由
--------------
(h = key.hashCode()) ^ (h >>> 16)
更多的特征值决定了hash之后的值。
TreeSet
---------------
2,集合的工具类
这一块之前学的有点弱,用的比较少。技术就是这样,如果学的不熟练,技术用起来很不方便。
Arrays这个工具类有诸如如下方法:
--排序
Arrays.sort(arr);
--填充
Arrays.fill(arr, 100);
--二分查询
Arrays.binarySearch(arr, -5);
--转换成数组
Arrays.asList()
对于集合也有类似的工具类:
Collections.fill(list, "tom");
Collections.reverse(list);
十七、IO
Input Output
-------------------
输出和输出.
System.out.println("");
设备之间数据传输.
Stream:
流的类型
-------------
数据类:
字节流:
字符流:
流向
输入流
输出流.
流的超类
-----------
InputStream
OutputStream
字符流
-----------
Reader //字符输入流
Writer //字符输出流
缓冲区字符流
--------------
缓冲区 : 8K
BufferedReader br = new BufferedReader(reader,size);
十八、并发
并发问题解决方案有两种:“速度”和“设计可管理性”。
java.util.concurrent并发包,Executor管理Thread对象。
Runnable不返回值,而Callable返回值。
sleep、yield、优先级、daemon线程(setDaemon)。基础基本知道了,再把concurrent包搞一搞
十九、eclipse
windows系统字体设置
--------------------
控制面板 -> 字体 -> Courier New -> 显式
eclipse
------------------
IBM
4000万美金
日食.
sun
空格或者中文目录.
IDE : 集成开发环境。
透视图:一组布局。View + Editor
改变主题
-----------------
eclipse -> windows -> preferences -> General -> Appearance -> windows classic + classic theme
windows -> show view -> other ...
eclipse快捷键
------------------
alt + / //内容辅助
ctl + alt + down //向下复制一行
ctl + alt + up //向上复制一行
alt + down //向下移动一行
alt + up //向上移动一行
ctl + d //删除一整行
ctl + shift + f //格式化代码
shift + enter //中途回车,不换行
ctrl + / //切换注释
ctrl + shift + / //块注释
ctrl + shift + \ //解除块注释
ctl + shift + T //搜索类
java单元测试
---------------------
@Test:加载非静态方法
@Before:加载非静态方法,在@Test之前运行
@BeforeClass:加载静态方法上,在类之前运行。
设置java编辑器字体
-------------------
eclipse -> windows -> preference -> appearance -> color and font -> java Editor font -> 字体Courier New 10号字体