CoreJava全套详细笔记心血放出资料_第1页
CoreJava全套详细笔记心血放出资料_第2页
CoreJava全套详细笔记心血放出资料_第3页
CoreJava全套详细笔记心血放出资料_第4页
CoreJava全套详细笔记心血放出资料_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

目录TOC\o"1-5"\h\z\o"CurrentDocument"原码、反码、补码 5\o"CurrentDocument"原码 5\o"CurrentDocument"反码 5\o"CurrentDocument"补码 5负数的补码转换为十进制数 6\o"CurrentDocument"char 6\o"CurrentDocument"运算符 6移位运算符 6位运算符 7逻辑运算符 7\o"CurrentDocument"流程控制 7\o"CurrentDocument"switch 7\o"CurrentDocument"break和continue 8\o"CurrentDocument"方法 8\o"CurrentDocument"构造方法 8\o"CurrentDocument"方法重载 8\o"CurrentDocument"this 9\o"CurrentDocument"继承 9\o"CurrentDocument"super 9\o"CurrentDocument"多态(polymorphism) 10\o"CurrentDocument"instanceof 10\o"CurrentDocument"static 11\o"CurrentDocument"final 11\o"CurrentDocument"abstract 12\o"CurrentDocument"类的加载 12触发类加载的几种情况 12类加载的顺序 12\o"CurrentDocument"接口(interface) 13\o"CurrentDocument"访问控制 14\o"CurrentDocument"Object类 15\o"CurrentDocument"clone() 15\o"CurrentDocument"对象克隆过程 15\o"CurrentDocument"浅复制和深复制概念 16\o"CurrentDocument"finalize() 16\o"CurrentDocument"equals(Objectobj) 16\o"CurrentDocument"toString() 16\o"CurrentDocument"String类及对象池 16\o"CurrentDocument"Stringa="hello"; 17\o"CurrentDocument"Stringc=newString("hello"); 17\o"CurrentDocument"StringBuffer和StringBuilder 17\o"CurrentDocument"主方法参数 18\o"CurrentDocument"方法的可变长参数 18\o"CurrentDocument"包装类 18\o"CurrentDocument"Number 19\o"CurrentDocument"自动封箱 /自动解封(Autoboxing/Unboxing) 19\o"CurrentDocument"对象池 19\o"CurrentDocument"内部类 20\o"CurrentDocument"意义 20\o"CurrentDocument"四种形式的内部类 20\o"CurrentDocument"静态内部类 20\o"CurrentDocument"成员内部类 21\o"CurrentDocument"局部内部类 22\o"CurrentDocument"匿名内部类 22内部类的应用 24\o"CurrentDocument"集合框架(CollectionFramework) 24\o"CurrentDocument"Iterator接口和Iterable接口 25\o"CurrentDocument"Connection接口和 Connections类 25\o"CurrentDocument"java.util.Collection 25\o"CurrentDocument"java.util.Collections 25\o"CurrentDocument"List(列表)接口 25\o"CurrentDocument"ArrayList 26\o"CurrentDocument"LinkedList 26\o"CurrentDocument"Vector 26\o"CurrentDocument"214 Set(集合)接口 26\o"CurrentDocument"HashSet 27\o"CurrentDocument"TreeSet 29排序的两种办法 29\o"CurrentDocument"java.Iang.Comparable(可比较的) 29\o"CurrentDocument"java.util.Comparator( 比较器) 30\o"CurrentDocument"Map 30\o"CurrentDocument"HashMap 30\o"CurrentDocument"Hashtable 31\o"CurrentDocument"Hashtable下的子类 Properties类 31\o"CurrentDocument"SortedMap接口下的 TreeMap类 31\o"CurrentDocument"泛型(Generic) 32\o"CurrentDocument"泛型特点 32\o"CurrentDocument"通配符 32\o"CurrentDocument"上限通配符: 32\o"CurrentDocument"下限通配符 33\o"CurrentDocument"总结: 33\o"CurrentDocument"运用 34\o"CurrentDocument"异常 34异常处理基础 34异常的类继承结构 34常见的未检查异常 35throw 35\o"CurrentDocument"自定义异常类 36\o"CurrentDocument"反射(Reflection) 37反射需要用到的类 37\o"CurrentDocument"java.lang.Class 37\o"CurrentDocument"java.lang.reflect.Field 38\o"CurrentDocument"java.lang.Package 38\o"CurrentDocument"java.lang.relect.Modifier 38\o"CurrentDocument"java.lang.reflect.Mothed 38\o"CurrentDocument"java.lang.reflect.Array 38\o"CurrentDocument"java.lang.reflect.Constructor 38242 三种获得某个类的Class对象的方法 38\o"CurrentDocument"Classc=Class.forName(”类名”); 38\o"CurrentDocument"Classc=类名.class; 39\o"CurrentDocument"Classc=对象名.getClass(); 39所能探查出来的类的特征 39通过反射生成一个类的实例 39\o"CurrentDocument"第一种方法 40\o"CurrentDocument"第二种方法 40\o"CurrentDocument"File 40\o"CurrentDocument"构造方法 40\o"CurrentDocument"重点方法 41\o"CurrentDocument"目录 42\o"CurrentDocument"流 42\o"CurrentDocument"字节流 42\o"CurrentDocument"字符流 44\o"CurrentDocument"节点流(NodeStream): 45过滤流(FilterStream) 45\o"CurrentDocument"ObjectInputStream和ObjectOutputStream 46\o"CurrentDocument"字节流转化成字符流的桥转换器 48文本文件和二进制文件 50\o"CurrentDocument"线程 50概念与原理 50操作系统中线程和进程的概念 50Java中的线程 51Java中的线程模型 51一些常见问题 51线程状态的转换 52线程的七种状态 52阻止线程执行 54线程的同步与锁 55同步和锁定 55静态方法同步 60如果线程不能获得锁会怎么样 60何时需要同步 61线程安全类 61线程死锁 62线程同步小结 63线程的交互 64线程交互的基础知识 64多个线程在等待一个对象锁时候使用notifyAll() 66守护线程(后台服务线程) 67并发协作-生产者消费者模型 68volatile关键字 68网络编程 69TCPSocket编程 69ServerSocket 70Socket 70UDPSocket编程 71DatagramSocket 71DatagramPacket 71原码、反码、补码原码将最高位作为符号位(以0代表正,1代表负),其余各位代表数值本身的绝对值(以二进制表示)。为了简单起见,我们用1个字节来表示一个整数:+7的原码为:00000111-7的原码为:10000111问题:+0的原码为:00000000-0的原码为:10000000反码一个数如果为正,则它的反码与原码相同;一个数如果为负,则符号位为1,其余各位是对原码取反。为了简单起见,我们用1个字节来表示一个整数:+7的反码为:00000111-7的反码为:11111000问题:+0的反码为:-0的反码为:补码利用溢出,我们可以将减法变成加法。对于十进制数,如果从9得到结果5,可以用减法:9-4=5;因为4+6=10,我们将6作为4的补数,将上式的减法改写为加法: 9+6=15;去掉高位1(也就是减去10),得到结果5。对于16进制数,如果从C得到结果5,可以用减法:C-7=5;因为7+9=16,我们将9作为7的补数,将上式的减法改写为加法: C+9=15;去掉高位1(也就是减去16),得到结果5。在计算机中,如果我们用1个字节表示一个数,一个字节有 8位,超过8位就进1,在内存中情况为:100000000,进位1被丢弃。一个数如果为正,则它的原码、反码、补码相同;一个数如果为负,则符号位为 1,其余各位是对原码取反,然后整个数加1。为了简单起见,我们用1个字节来表示一个整数。+7的补码为:00000111-7的补码为:1111100114负数的补码转换为十进制数a、 先对各位取反;b、 将其转换为十进制数;c、 加上负号,再减去1。例如:11111010,最高位为1,是负数,先对各位取反得00000101,转换为十进制数得5,加上负号得-5,再减1得-6。charchar类型(2字节)用于表示Unicode编码的字符单元;char类型用于表示单个字符,通常用来表示字符常量。例如:'A'是编码为65所对应的字符常量。Unicode编码单元可以表示为十六进制值,其范围从 \u0000到\uffff。除了可以米用转义序列符\u表示Unicode代码单兀的编码之外,还有一些用于表示特殊字符的转义序列符。如:转义序列名称Unicode值\b退格(Backspace)\u0008\t制表(Tab)\u0009\n换行(Linefeed)\u000a\r回车\u000d双引号(Doublequote)\u0022单引号(Singlequote)\u0027\\反斜杠(Backslash)\u005c尽管char不是整数,但在许多情况中你可以对它们进行运算操作就好像他们是整数一样,这允许你可以将2个字符相加,或对一个字符变量值进行增量操作。运算符移位运算符只能针对二进制数据(整数)<<左移,左移一位相当于原来的数乘二,大于 32位的话高出的位就不要了,如果移动的位数大于32的话java会自动把这个位数变为这个数对 32求余的值;>>右移,右移一位相当于除2取整,两位相当于连续除2取整而不是除4取整,看正数还是负数,正数右移的话高位补 0,负数的话补1;>>>无符号右移(算数右移),不考虑符号位,移进来的都补 0。32位运算符&按位与,两个数按位与,全部转换成二进制后按位比较, 全为1才是1,其它是0,返回一个新的整数;|按位或,两个数按位或,全部转换成二进制后按位比较, 全为0才是0,其它是1,返回一个新的整数;A按位异或,两个数的二进制位数比较, 相同结果为0,相异结果为1;~按位求反,把一个数二进制的每一位都反过来。逻辑运算符&&短路与,两边如果左边是假的话就不再判断右边的,直接返回假;II短路或,两边如果有一个为真的就不再判断右边的,直接返回真;&与,不管怎样两边都会判断,都为真才返回真;I或,不管怎样两边都会判断,都为假才返回假。流程控制switcha、 switch后括号中的值必须是int,byte,char,short,枚举类型的变量之一,其它类型的就不行了;b、 每个case后面的值必须是不相等的,而且 必须是常量;c、 如果每个case冒号后面的语句执行完后没有 break,还会继续执行后面 case里的语句,所以在每个case的语句结束后加一个break;d、 多个case可以可并到一起,表示或的关系;e、 default代表如果和所有case后的值都不匹配,就执行这里的语句。无论 default写哪都是最后执行的。publicclassGrade{publicstaticvoidmain(String[]args){Scannersca=newScanner(System.in);System.out.println( ”请输入一个百分数: ”);ints=sca.nextInt();if(s<0||s>100){System.out.println( "ERRORDATA:S");System.exit(0); //退出这个程序}switch(s/10){case10:case9:System.out.println("A");breakcase8:System.out.println("B");breakcase7:System.out.println("C");breakcase6:System.out.println("D");breakdefault:System.out.println("E");break}42break和continuea、break退出当前的循环体,在嵌套循环中,只退出当前的 一层循环;b、 continue结束当前本次循环,继续进行下一轮的循环。可以说,只是本次忽略循环内后面的语句;c、 continue只能在循环体内用;d、break可以用在任意代码块中,表示退出当前程序块 (配合标签使用,很好用)。方法构造方法每次在创建实例变量,对类中的所有变量都要初始化是很乏味的。 如果在一个对象最初被创建时就把对它的设置做好, 那样的话,程序将更简单并且更简明。 因为对初始化的要求是共同的,Java允许对象在他们被创造时初始化自己。 这种自动的初始化是通过使用构造方法来完成的。构造方法在对象创建时初始化。一旦定义了构造方法,在对象创建后,在 new运算符完成前,构造方法立即自动调用。 构造方法看起来有点奇怪, 因为它没有任何返回值,即使是void型的值也不返回。这是因为一个类的构造方法内隐藏的类型是它自己类的类型。构造方法的任务就是初始化一个对象的内部状态,以便使创建的实例变量能够完全初始化,可以被对象马上使用。方法重载在Java中,同一个类中的2个或2个以上的方法可以有同一个名字,只要它们的参数声明不同即可。在这种情况下,该方法就被称为重载( overloaded)。当一个重载方法被调用时,Java用参数的类型和(或)数量来表明实际调用的重载方法的版本。因此,每个重载方法的参数的类型和(或)数量必须是不同的。当一个重载的方法被调用时,Java在调用方法的参数和方法的自变量之间寻找匹配。 但是,这种匹配并不总是精确的。 在一些情况下,Java的自动类型转换也适用于重载方法的自变量。例如:classOverloadDemo{voidtest(doublea){System.out.println("Insidetest(double)a:"+a);}}classOverload{publicstaticvoidmain(Stringargs[]){OverloadDemoob=newOverloadDemo();inti=88;ob.test(i);}}OverloadDemo的这个版本没有定义test(int)。因此当在Overload内带整数参数调用test()时,找不到和它匹配的方法。但是,Java可以自动地将整数转换为 double型,这种转换就可以解决这个问题。因此,在 test(int)找不到以后,Java将i扩大到double型,然后调用test(double)。当然,如果定义了 test(int),当然先调用test(int)而不会调用test(double)。只有在找不到精确匹配时,Java的自动转换才会起作用。thisthis等价于当前对象,调用当前对象的属性或方法就用 this.属性名,或this.方法名()。当前对象:指谁在调用当前这个方法和属性, 谁就是当前对象。在定义类的时候是不存在当前对象的。在局部变量与外部变量同名的时候, 为了区分,就要在外部变量的前面加一个 this来表示这个变量是类的全局变量。继承尽管子类包括超类的所有成员,它不能访问超类中被声明成 private的成员。子类的对象可以调用父类的一切公有的变量和方法,也可以扩展自己新的属性和方法,但是新扩展的部分父类的对象是无法调用的。super在子类的构造方法中调用父类的构造方法,并且 super要放在第一行,不能与this一起用,主要用为在构造子类的时候给父类中定义的变量赋值:a、 任何子类的构造方法都会调用父类的构造方法:因为调用构造方法和创建一个对象是绑在一起的,而一个子类对象的一部分可以看做是父类对象,所以当创建一个子类对象时一定是先创建一个父类的对象,再在父类对象的基础上扩展(extends)成一个子类对象。注意:自始至终只创建了一个对象,因为创建的那一个子类对象的一部分是父类对象(上帝想创造一个科学家,肯定是先创造一个人,在人的基础上进行教育培训等,最终变成一个科学家,而最初的人和最后的科学家其实是一个对象);b、任何子类的构造方法的第一行必须是 this(...)或super(...)的调用,如果程序员不写,则系统会隐含的调用 super(),也就是说子类无论如何都会调用父类的构造方法,没写就调用父类的无参构造方法;c、子类构造方法的第一行只能出现this(...),super(...)这两种情况,无论怎么调用,最终总能找到父类构造方法,否则造成死循环。因为如果子类的某个构造方法的第一行出现this(...),此时系统不会加上缺省的 super(…)那么this(...)会调用子类的其他构造方法,所以子类的构造方法之间开始调用,如果子类的所有的构造方法的第一行全都是this(...)那便构成了一个死循环。多态(polymorphism)a、 对象的多态:一个对象多种形态。方法的重载和覆盖就是方法多态的一种体现;b、对象多态的基础:子类对象可以当作父类对象来看,例如: Animala=newBird();c、 多态定理:如果我们把子类对象当作父类对象来看,那么就只能访问父类中已有定义的属性和方法(不能访问子类扩展的属性和方法)。如果子类覆盖了父类的方法,再把子类对象当作父类对象去调用该方法时,调用的是子类覆盖后的方法(对象的行为不可能因为你把它当作什么来看而改变);d、 Animala=newBird()左边是编译时类型:在代码编译过程中,编译器把这个对象当作什么来看?(父类对象)右边是运行时类型:在代码执行过程中,JVM把这个对象当作什么看?(子类对象)。左边是主观认为(我们把a当作什么看?),右边是客观存在(a实际是什么)。当你把鸟当动物看时,你知道它是动物,但你不知道它是鸟,所以你知道它会走会吃,但你不知道它会唱歌(相当于编译器把它当Animal),所以你不会试图去调用它的唱歌的方法,因为你根本就不知道它会唱歌。当你调用 move()方法时,它会flying,因为它本质上还是个鸟,不会因为你把它当作动物而不会飞用走的路。instanceof当发生多层次复杂的继承机构时,往往使程序员自己都搞不清楚最后这个对象到底是什么了,这时就需要提供一个方法来判断一下了。判断一个对象是不是某一个类型的实例,看这个对象能不能作为这个对象实例来看(看这个对象运行时的类型,即看这个对象的客观存在是什么) 。static描述整体特征而不是个体特征的属性时,用静态修饰符;有时你希望定义一个类成员,使它的使用完全独立于该类的任何对象。通常情况下,类成员必须通过它的类的对象访问,但是可以创建这样一个成员,它能够被它自己使用,而不必引用特定的实例。成员的声明前面加上关键字static就能创建这样的成员。如果一个成员被声明为static,它就能够在它的类的任何对象创建之前被访问,而不必引用任何对象。你可以将方法和变量都声明为static,static成员的最常见的例子是main(),因为在程序开始执行时必须调用main(),所以它被声明为static。声明为static的变量实质上就是全局变量,当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量。?声明为static的方法有以下几条限制a、 它们仅能调用其他的static方法;b、 它们只能访问static数据;c、 它们不能以任何方式引用this或super。?静态变量和非静态变量(实例变量)的差别a、 空间分配时机:静态变量是在类加载的时候分配空间,非静态对象是在生成对象的时候分配空间;b、 空间分配方式:不管有多少对象静态变量只有一份(所有对象共享),非静态变量有多少对象就分配多少个空间;c、 访问方式:静态变量是:类名.属性,比如Animal.COUNT;非静态变量:对象名.属性,比如。?静态方法和非静态方法的区别a、 静态方法是通过类名来调用,非静态方法是通过对象来调用;b、 静态方法中不能访问本类的非静态成员,但非静态方法可以访问静态成员;c、 静态方法不存在多态特性,也就是静态方法无法被子类覆盖,父类对象调用此方法还是父类的。?静态代码块a、 静态代码块会在类被加载时被系统自动执行;b、 一般可以在静态代码块中给静态属性赋值;c、 类的静态代码块只能有一个。finala、 声明为final的变量在实例中不占用内存;b、 一个final变量实质上是一个常数;c、 修饰属性时属性不可变,并且属性在声明的时候必须初始化,或者在构造方法中初始化一般与static一起用,一旦定义了,就不能再变了;d、 修饰方法时方法不能被覆盖;e、 修饰类是类不能被继承,表示最终的类,不能有子类;f、修饰局部变量时局部变量不可变(常量)。abstracta、 用来修饰类和方法;b、 修饰类的话表示这个类是个抽象类,抽象类不能被实例化(生成对象) ;c、 修饰方法的话表示这个方法是个抽象方法,抽象方法没有方法体;d、 如果一个类包含有一个抽象方法,那么这个类必须是抽象类;e、 如果一个类不包含抽象方法,那么该类也可以被定义成抽象类;f、 抽象类不能被实例化,但却可以定义引用;g、 抽象类一般需要实现--定义一个子类,并实现抽象方法;h、 抽象类也是有构造方法的,因为需要被子类调用;i、 子类必须实现父类的抽象方法;j、 abstract和final不能共同修饰一个类或方法;k、 例如:定义一个Animal类,就可以定义成抽象类,move()方法可以定义成抽象方法,当具体的子类继承Animal时,再覆盖move()方法,鸟飞,鱼游 类的加载触发类加载的几种情况a、 调用静态成员时,会加载静态成员真正所在的类及其父类;b、 通过子类调用父类的静态成员时,只会加载父类而不会加载子类;c、 第一次new对象的时候加载(第二次再new同一个类时,不需再加载);d、 加载子类会先加载父类(覆盖父类方法时所抛出的异常不能超过父类定义的范围)e、 如果静态属性有final修饰时,则不会加载,当成常量使用,例如:publicstaticfinalinta=123;但是如果上面的等式右值改成表达式(且该表达式在编译时不能确定其值)时则会加载类,例如:publicstaticfinalinta=math.PIf、 如果访问的是类的公开静态常量,那么如果编译器在编译的时候能确定这个常量的值,就不会被加载,如果编译时不能确定其值的话,则运行时加载。类加载的顺序?加载静态成员/代码块先递归地加载父类的静态成员/代码块(Object的最先),再依次加载到本类的静态成员。同一个类里的静态成员/代码块,按写代码的顺序加载。如果其间调用静态方法,则调用时会先运行静态方法,再继续加载。同一个类里调用静态方法时,可以不理会写代码的顺序。调用父类的静态成员,可以像调用自己的一样,但调用其子类的静态成员,必须使用 子类名.成员名”来调用。?加载非静态成员/代码块(实例块在创建对象时才会被加载,而静态成员在不创建对象时可以加载)先递归地加载父类的非静态成员 /代码块(Object的最先),再依次加载到本类的非静态成员。同一个类里的非静态成员 /代码块,按写代码的顺序加载。同一个类里调用方法时,可以不理会写代码的顺序。 但调用属性时,必须注意加载顺序。一般编译不通过,如果能在加载前调用,值为默认初始值(如:null或者0)。调用父类的非静态成员(private除外),也可以像调用自己的一样。?调用构造方法先递归地调用父类的构造方法(Object的最先),默认调用父类空参的,也可在第一行写明调用父类某个带参的。 再依次到本类的构造方法, 构造方法内,也可在第一行写明调用某个本类其它的构造方法。注意:如果加载时遇到override的成员,可看作是所需创建的类型赋值给当前类型。其调用按多态用法:只有非静态方法有多态 ;而静态方法、静态属性、非静态属性都没有多态。假设子类override父类的所有成员,包括静态成员、非静态属性和非静态方法。由于构造子类时会先构造父类, 而构造父类时,其所用的静态成员和非静态属性是父类的, 但非静态方法却是子类的,由于构造父类时,子类并未加载,如果此时所调用的非静态方法里有成员,则这个成员是子类的,且非静态属性是默认初始值的。1、加载父类静态成员/代码块2、加载子类静态成员/代码块旦3、 加载父类非静态成员/代码块—旦—4、 加载父类构造方法5、 加载子类非静态成员/代码块6、 加载子类构造方法接口(interface)a、 接口可以通过运用关键字extends被其他接口继承;b、当一个类实现一个继承了另一个接口的接口时, 它必须实现接口继承链表中定义的所有方法;c、 是一种抽象的数据类型,特殊的抽象类;d、接口中的所有方法都是抽象方法,就算不写系统也会自动加上 abstract,所以一般就省去不写了;e、 接口中所有的属性都是finalstatic的(静态常量),就算不写系统也会自动加上,所以一般可以省去不写了;f、接口也不能被实例化,但可以定义的接口的引用;g、接口没有构造方法,接口的实现类在生成对象时不会调用接口的构造方法, 类的子类在生成对象时一定要调用父类的构造方法 (所以子类长的像父类,却不像接口);h、 一个类只能继承一个父类,但是可以实现多个接口,用逗号隔开;i、 接口之间可以多继承;j、 接口=标准:把服务的使用者和服务的提供者分开,降低系统的耦合,有效的提高软件的可扩展性和可维护性;k、接口声明中可以声明变量, 它们一般是final和static型的,意思是它们的值不能通过实现类而改变,它们还必须以常量值初始化,如果接口本身定义成 public,所有方法和变量都是public的。访问控制访问控制(accesscontrol)访问指示符(accessspecifier)Private成员UU的成员ProlePublic^员同一类中可见是是是是同一个包中对子类町见同一个包中对非子类可见否是是不同包巾对子矣否不同的包中对卓子类可见習否否是staticfinalabstractpublicprotected默认private顶层类NYYYNYN属性YYNYNYY方法YYYYYYY局部变量NYNNNNN成员式内部类YYYYYYY局部式内部类NYYNNNNObject类构造方法只有唯一的一个,并且无参。clone()protectedObjectcione()throwsCioneNotSupportedException创建并返回一个当前对象的拷贝,得到和当前对象一模一样的对象。clone()方法满足:a、 对任何的对象x,都有x.clone()!=x;克隆对象与原对象不是同一个对象了;b、 对任何的对象x,都有x.clone().getClass==x.getClass();克隆对象与原对象的类型一样;c、 如果对象x的equals方法定义恰当,那么x.clone().equals(x)应该成立。对象克隆过程? 要让这个类实现java.lang.Cloneable接口Cloneable接口,指示Object.clone()方法可以合法地对该类实例进行按字段复制。如果在没有实现Cloneable接口的实例上调用Object的clone方法,则会导致抛出CioneNotSupportedException异常。按照惯例,实现此接口的类应该使用公共方法重写 Object.clone(它是受保护的)。注意,此接口不包含clone方法。因此,因为某个对象实现了此接口就克隆它是不可能的。即使clone方法是反射性调用的,也无法保证它将获得成功。Cloneable接口没有任何方法, 像Cloneable这样的接口叫做标记接口, 即标记这个类的实例可以调用clone方法,只是起到一个标记的作用。?覆盖Object中的clone()方法,并将访问权限改为 publicclone();方法的访问修饰符是 protected,这意味着,在子类中直接去super.clone();是可以的,但是如果想在第三方类中去生成一个子类对象后再取调用 cione()时就不可以了,所以这时就得在子类中去覆盖 Object的clone方法,并将访问控制修饰符改为 public。如果只是希望浅复制,那么使用这样的代码就可以完成publicObjectcione()throwsCioneNotSupportedException{returnsuper.clone();}这段代码表示,覆盖Object中的clone方法,将访问控制修饰符改为 public,然后再去调用Object的clone方法。clone方法有具体的实现步骤代码, 这叫做是实现方法。因为clone方法涉及到底层数据的访问, 一般的程序员是没有办法写出这些代码的, 所以用这样的一个简单的步骤就可以达到 clone的目的了。14.12浅复制和深复制概念?浅复制(浅克隆)被复制对象的所有变量都含有原来的对象的相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不是复制它所引用的对象。?深复制(深克隆)被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象, 而不再是原有的那些被引用的对象。 换言之,深复制把要复制的对象所引用的对象都复制了一遍。例如:一个Student对象包含ID,姓名,Teacher等属性。其中ID为基本类型,姓名为String类型,Teacher为一个Teacher对象。浅复制只复制一个新的ID,而姓名和Teacher只复制地址。即,复制后的新对象姓名和Teacher仍然指向原先的Stuent的姓名和Teacher。而深复制会连同姓名和Teacher也同样复制出来,并且与原对象的地址不同,指向不同的对象。finalize。a、构造方法负责对象创建后的初始化, finalize方法负责对象消亡时的资源释放;b、 finalize方法被垃圾收集器自动调用,而垃圾收集器有可能根本不执行,所以没有办法保证finalize方法一定执行。equals(Objectobj)下面是Object中的equals方法源码:publicbooleanequals(Objectobj){|return(this==obj);}toString()返回该对象的字符串表示。通常, toString方法会返回一个"以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。Object类的toString方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:getClass().getName()+@'+Integer.toHexString(hashCode())String类及对象池在JDK5.0里面,Java虚拟机在启动的时候会实例化 9个对象池,这9个对象池分别用对象池的存在是为了避免频繁的创建和销毁对象而影响系统性能。 对象池是独立于栈空间和堆空间的,保存着指向一些对象的首地址。Stringa="hello";首先把hello这个对象创建出来,并保存在堆中。然后对象池会保存一个指向 hello的首地址。如果a是某个方法内的局部变量,那么也会在栈中将 hello的首地址保存在a中。如果a的地址值被赋为null,也就是a不再指向hello了,此时hello并没有成为垃圾,因为对象池中始终保存了 hello的首地址指向hello。而对象池中的那些地址值,程序员是不能直接管理的,那是由 JVM才能直接管理的。下次如果需要Stringb="hello";创建"hello"对象,那么b会去对象池中找那些地址值, 如果找到了指向hello对象的地址,那么会将这个地址直接赋给 b。如果没有与之匹配的,才会创建新的对象,并同样将这个对象的首地址保存在对象池中。Stringc=newString("hello");系统会直接在堆空间中创建一个新的 hello对象,而不会去对象池中找,而且这样创建的新的hello对象也不会保存在对象池去。注意注意:Strings=newString("hello");直接只有这条语句的时候,这里的 hello作为一个参数传给String,而此时没有hello这个对象,那么:首先会创建一个hello对象,并且将这个hello对象的首地址保存在对象池中,然后将这个hello对象作为参数传给String,此时又new了一个新hello对象,而s中保存的是新的hello对象的首地址。所以只有这条语句的时候,实际上是创建了两个 hello对象。StringBuffer和StringBuilder当我们需要对字符串频繁的进行修改时, 最好不要用String类,因为那会产生很多垃圾,降低系统效率。在java.lang包下,有两个StringBuffer和StringBuilder类,是更好的选择。因为用它们new出来的字符出对象是可以更改的,而且会在原字符串的基础上进行更改,而不会向String那样创建新的字符串对象,所以避免了垃圾的产生。而StringBuffer和StringBuilder的唯一区别是:StringBuffer是线程安全的(Thread-safe)字符序列;StringBuider是线程不安全的字符序列。主要关注点:一是构造方法,二是众多重载的append(追加)和insert(插入)方法。publicclassStringBufferTest{publicstaticvoidmain(String[]args){StringBuffers=newStringBuffer();for(charc='A';c<='Z';c++){s.append(c);}System.out.println(s.toString());}}主方法参数java类名命令后面还可以给一些主方法的参数,这些参数都被系统当作字符串放到main方法声明的参数String[]args中,如果输入多个参数的话就以空格为分隔符依次把每个参数放入args数组。如果不传参数的话 args就是一个0个元素的数组。在eclipse中给主方法传参数:右键runasrunconfigurationsMainclass要是现在要运行的类,如果不是就要search找到arguments在上面的栏中就是给main方法传的参数,填上参数applyRun。在把这些参数传给主方法之前, JVM会先对这些参数做一个包装,把它们先包装成一个字符串数组之后再传给主方法。所以主方法的参数是 String[]args。方法的可变长参数其实当我们把不同长度的参数传给方法时, 编译器会对这些参数做一个包装, 把它们包装成一个数组之后再传给方法,所以方法得到的还是一个数组。所以方法的可变长参数实际上是数组的一种特殊的表现形式。在定义方法的时候知道要传的参数的类型, 但是参数的数量不固定的时候就用可变长参数,可变长参数类型的写法,例如: publicstaticvoidm(String...strs){}上面的参数类型在String后面多了...,这样在调用方法传参数的时候就可以传多个参数或者一个参数,也可以不传参数,但参数必须都为String类型的,如果要传其它类型的时候在定义的时候改成其它类型,然后在类型后面加上 …就可以了。如何使用这些参数:在方法中此参数是被当作数组类访问的, 调用length就可以知道有多少参数传进来,这种参数既能接受单个元素做参数, 也可以接受数组作参数。也就是说可变长的参数类型兼容了数组参数类型,但是数组参数类型不能兼容可变长参数类型。使用可变长参数的规定:a、一个方法只能有一个可变长参数,而且该参数必须是这个方法的最后一个参数;b、可变长参数的方法只有在必须的时候才被调用, 也就是说,如果有不可变长参数的方法可以匹配,这种调用,那么系统会优先选择不可变长参数的方法的调用。包装类Java使用简单的类型,例如整型(int)和字符(char)。这些数据类型不是对象层次结构的组成部分。它们通过值传递给方法而不能直接通过引用传递。 而且,也没有办法使两种方法对整型(int)引用同一实例(sameinstanee)。有时需要对这些简单的类型建立对象表达式。为了满足这种需要,Java提供了与每一个简单类型相应的类。 本质上,这些类在类中包装(wrap)简单类型。因此,它们通常被称作类型包装器( wrappers)。Number抽象类Number是BigDecimal、Biglnteger、Byte、Double、Float、Integer、Long和Short类的超类。Number的子类必须提供将表示的数值转换为 byte、double、float、int、long和short的方法。抽象类Number定义了一个由包装数字类型字节型(byte),短整型(short),整型(int),长整型(long),浮点型(float)和双精度型(double)的类实现的超类。Number有返回上面不同数字格式的对象值的抽象方法。也就是, doubleValue()方法返回双精度(double)值,floatValue()方法返回浮点(float)值等。自动圭寸箱/自动解圭寸(Autoboxing/Unboxing)在JDK1.5之前要获得一个基本类型的对象比如 Integer只能用Integeri=newInteger(5)或者Integeri=Integer.valueOf(5)但在JDK1.5以后可以直接写成Integeri=5;在这里虚拟机默认的为这个基本数据类型进行了包装,以上面的第二种形式即:Integeri=Integer.valueOf(5);这种自动的包装叫做自动封箱。另外还可以自动解封,比如:inta=i;这种形式就相当与inta=i.intValue();对象池除了字符串类型的对象会创建对象池, 八种基本类型的包装类也会创建对象池。 但是这些包装类new出来也只创建一个对象,Integer的对象池在启动的时候就创建好了,范围是-128~127之间,所以在这之间的数字对象都不会再创建新对象,超出的部分都会再创建新对象,不会在从对象池中拿。例如:Integeri1=5;//对象池中拿Integeri2=5;//i1==i2Integeri3=newInteger(5);//重新创建一个对象,所以 i2!=i3同理String的另一个特点,Integer对象的值也是不可改变的。所以频繁的创建修改Integer对象也会生成很多垃圾。但是 Integer的根本是int基本类型,所以直接用int就可以了。像:for(inti=0;i<1000000;i++)而不用复杂的把i定义成Integer。publicclass IntegerTest{publicstaticvoidmain(String[]args){Integeri1=5;Integeri2=Integer. valueOf(5);Integeri3=newInteger(5);System.out.println(i1==i2);System.out.println(i1==i3);System.out.println(IIIntegeri4=250;Integeri5=Integer.valueOfIntegeri6=newInteger(250);System.out.println(i4==i5);System.out.println(i4==i6);//上面两种形式都是从对象池中拿对象,所以它们相等(250);内部类意义a、 更小的层次的封装,把一个类隐藏在另外一个类的内部;b、 能方便的在内部类中访问外部类的私有成员。四种形式的内部类a、静态内部类、成员内部类统称成员式内部类, 与成员变量、成员方法处于一个级别;b、 静态内部类就像静态成员一样,成员内部类就像实例成员一样;c、 局部内部类、匿名内部类统称局部式内部类,与方法内的局部变量处于一个级别。静态内部类a、 不能访问外部类的非静态成员;b、在外面访问此类的话就用:外部类名 .内部类名;c、 创建了一个静态内部类对象语法:外部类名•内部类名变量=new外部类名•内部类构造函数()例如:OuterA.InnerAinn=newOuterA.InnerA();d、静态内部类和外部类对象实际上没什么关系的, 静态内部类与外部类的关系类似于寄居关系,寄居只是借外部类的壳把自己隐藏起来, 在生成内部类对象时不需要外部类对象。2022.成员内部类a、 可以访问外部类的静态和非静态成员;b、生成一个成员内部类对象要复杂的多, 生成一个成员内部类对象之前必须先生成一个外部类对象:外部类名.内部类名对象名=外部类对象.new内部类名();例如:OuterAout=newOuterA();OuterA.InnerBinnb=out.newInnerB();c、成员内部类与外部类的关系类似于寄生关系, 在生成内部类对象时必须要有外部类对象,一个内部类对象一定对应着一个外部类对象。如何选择用静态内部类或成员内部类a、 如果外部类怎么变化都不影响内部类的话,那么推荐用静态内部类;b、 如果操作内部类的改变能影响外部类,那么推荐使用成员内部类。publicclass InnerClassTest1{publicstaticvoidmain(String[]args){//这里的OuterA就好像是InnerA外面的一层包一样,这和调用包里的类的方式差不多。OuterA.InnerA();newOuterA.InnerAinna=inna.m1();//先生成一个外部类对象,之后用这个外部类对象OuterAout=newOuterA();OuterA.InnerBinnb=out.new一个内部类对象。newInnerB( "hello");innb.m2();}}classprivateStringname1="hello" ;privatestaticStringname2="haha"publicstaticclassInnerA{public voidm1(){OuterA{;//name2是静态成员//System.out.println(namel);//System.out.println(不能访问外部类的非静态成员。name2);}}publicclassInnerB{ //InnerB(Stringname){成员内部类InnerBpublic}publicvoidm2(){//既能访问静态成员也能访问非静态成员。System.out.println(System.out.println(namel);name2);2023.局部内部类a、 在方法体里定义的类;b、 局部内部类里不能定义静态的属性和方法;c、局部内部类只能访问外部类中用 final修饰的常量;d、 如何在方法体外得到这个类的对象呢,通过方法的返回值就可以,返回值类型为Object。但是外部得到的这个对象是没什么意义的, 因为只能访问Object里的方法,此类自己的方法是访问不到的。 解决方法:在外部定义一个接口, 然后此局部内部类来实现接口,并实现接口中的方法,然后外部拿到对象后转化成此接口类型就行了。再调用接口中的方法时,实际上是调用的局部内部类中实现接口的方法。匿名内部类a、 没有名字的局部内部类;b、 匿名内部类没有构造函数(因为没有名字) ,也不能被继承;c、 匿名内部类可以访问外部类的成员:外部类名 .this•成员;d、 匿名内部类如果声明在方法中的话也具有局部内部类的特点,只能调用 final的局部变量;e、 匿名内部类中不能声明静态的成员;f、 匿名内部类的声明:声明类型变量=new[类名extends/implements]声明类型(){类的方法声明...}[]中的是省略的部分;g、 匿名内部类的声明和对象的生成是合二为一,不可分割的;h、 得到的对象不知道是哪个类的对象, 只知道是实现了某接口或者继承了某类的类的对象。publicclassInnerClassTest{publicstaticvoidmain(String[]args){OuterBout=newOuterB();//实例化一个Mylnter对象,在调用其中的方法,这时, 实际上调用的是实现它的内部类的方法。MyInterobj=out.m1();obj.innerm();OuterCoutc=newOuterC();outc.m2(newMyInter(){publicvoidinnerm(){Mylntermyc= newMylnter(){publicvoidinnerm(){}};newMylnter(){publicvoid innerm(){}}.innerm();}}classOuterB{publicMyInterm1(){ // 返回一个Mylnter接口对象inta=10;finalintb=20;//实现Mylnter接口,并实现其中的方法。classInnerCimplementsMylnter{publicvoidinnerm(){System.out.println( "InnerC.innerm()" );//System.out.println("a="+a);System.out.println( "b="+b); //只能访问外部类的常量。}}//返回一个内部类的对象。returnnewInnerC();}}//定义一个Mylnter接口,让局部内部类去实现接口中的方法interface Mylnter{publicvoidinnerm();}classOuterC{//1、定义一个匿名内部类,实现Mylnter接口,而且给出方法的具体实现。 2、生成该实现类的对象。(new)publicMylnterm1(){returnnewMylnter(){publicvoidinnerm(){

publicvoidm2(Mylntermyi){}}203 内部类的应用a、 如果一个类需要在多个类中使用,则考虑使用普通公开类;b、 如果一个类需要在一个类中多个方法里使用,考虑使用成员内部类;c、 如果一个类需要在某个方法里多次使用,考虑使用局部内部类;d、 如果一个类需要在某处使用一次,考虑使用匿名内部类。集合框架(CollectionFramework)a、 数组的缺点:不能自动扩容,在刚创建数组时数组的空间不好确定;b、集合是一种数据结构,为了实现快速处理和高效的内存利用率, 集合实现经过精心构造,集合通过其方便的功能鼓励软件的复用;c、 集合用来存储数据一般能自动扩容,而且方便遍历。Iterator接口和Iterable接口a、 Iterator:对collection进行迭代的迭代器(对集合对象循环访问的工具);b、 Iterable:可迭代的,该接口是所有Collection集合的超级接口;c、 Iterable接口和Itertor接口没有继承与被继承的关系;d、 Iterable接口中只有一个方法:publicIteratoriterator(){},第一个Iterator是返回值类型,第二个iterator是方法名,所以此方法返回一个Iterator对象,这是Iterable接口和Itertor接口唯一联系;e、 因为所有的集合都实现了Collection接口,而Collection接口又实现了Iterable接口,Iterable中只有唯一的一个方法iterator,所以所有的集合对象都可以调用iterator方法,而调用iterator方法会返回一个Iterator对象,这样就可以调用Iterator中的方法了。Connection接口和Connections类java.util.Collectiona、Connection接口是集合层次结构中的根接口, Set和List都是其派生出来的子接口,它定义了在集合中添加、清除、遍历元素的操作;b、 注意:add方法只能添加引用类型,而不能添加基本数据类型(可以使用包装类)因为基本数据类型是存放在栈中的;c、remove方法移出对象时,会去调用对象的 equals方法,判断对象是否相同;d、所有通用的Collection实现类应该提供两个"标准”构造方法:一个是void(无参数)构造方法,用于创建空collection;另一个是带有Collection类型单参数的构造方法,用于创建一个具有与其参数相同元素新的collection;java.util.Collectionsa、 Connections类提供了集合的静态方法,其中很多方法实现了用于查找和排序等功能的多态算法;b、 还提供了很多synchronized方法,可以直接调用这些方法,将线程不安全的Collection包装成线程安全的Collection,这种方法很方便灵活;c、 Collections中有个Sort方法用于给List排序,Collections.Sort()分为两部分,一部分为排序规则,一部分为排序算法;规则用来判断对象,算法是考虑如何排序;d、 对于自定义对象,Sort不知道规则,所以无法比较,这种情况下一定要定义排序规则,方式有两种(见排序的两种办法);e、 reverse方法,自动反向排序。List(列表)接口有序存放、允许重复ArrayLista、底层是数组实现的,实现了数组的变长,初始的数组容量默认是 10;b、数组实现,遍历快,增加删除效率低;c、 ArrayList支持可随需要而增长的动态数组:标准数组是定长的,在数组创建之后,它们不能被加长或缩短,这也就意味着你必须事先知道数组可以容纳多少元素。但是,你直到运行时才能知道需要多大的数组。为了解决这个问题,类集框架定义了ArrayList。本质上,ArrayList是对象引用的一个变长数组。也就是说,ArrayList能够动态地增加或减小其大小。数组列表以一个原始大小被创建。当超过了它的大小,类集自动增大,当对象被删除后,数组就可以缩小;d、 尽管当对象被存储在ArrayList对象中时,其容量会自动增加,仍可以通过调用ensureCapacity()方法来人工地增加ArrayList的容量。在开始时,通过一次性地增加它的容量,就能避免后面的再分配,因为再分配是很花时间的;e、 相反地,如果想要减小在ArrayList对象之下的数组的大小,以便它有正好容纳当前项的大小,可以调用trimToSize()方法;f、 有时想要获得一个实际的数组,这个数组包含了列表的内容,可以通过调用方法toArray()来实现它,下面是几个为什么可能想将类集转换成为数组的原因:对于特定的操作,可以获得更快的处理时间;为了给方法传递数组,而方法不必重载去接收类集;为了将新的基于类集的程序与不认识类集的老程序集成。LinkedLista、 实现了队列(Deque)的接口,底层是链表实现的,先进先出;b、 链表实现,遍历较慢,增加删除效率高;c、 此类实现Deque接口,为add、poll提供先进先出队列操作,以及其他堆栈和双端队列操作;d、 所有操作都是按照双重链接列表的需要执行的,在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。Vector数组实现(和ArrayList一样),同步的,线程安全,重量级的。(牺牲了效率,提高数据的安全性);而ArrayList是线程不安全的。Vector类现在已经很少用了,因为现在的JDK提供了一个Collections类,该类中提供了很多synchronized的方法,可以将一个线程不安全的Collection包装成一个线程安全的Collection。这比使用Vector要更方便更灵活。Set(集合)接口无序存放,不可重复。只有一个add方法,因为它是无序的,而List中有两个add方法。其他的一些和下标有关的方法,在Set里面都没有。常用的方法:clear、contains、isEmpty、remove、size、toArray。HashSet数组和链表实现的。 不排序的,不能重复的(hashCode相同,则覆盖)。HashSet扩展AbstractSet并且实现Set接口。它创建一个类集, 该类集使用散列表进行存储。正像大多数读者很可能知道的那样,散列表通过使用称之为散列法的机制来存储信息。在散列(hashing)中,一个关键字的信息内容被用来确定唯一的一个值,称为 散列码(hashcode)。而散列码被用来当做与关键字相连的数据的存储下标。关键字到其散列码的转换是自动执行的——你看不到散列码本身。你的程序代码也不能直接索引散列表。下面的构造函数定义为:HashSet()HashSet(Collectionc)HashSet(intcapacity)HashSet(intcapacity,floatfillRatio)第一种形式构造一个默认的散列集合。第二种形式用c中的元素初始化散列集合。第三种形式用capacity初始化散列集合的容量。第四种形式用它的参数初始化散列集合的容量和填充比(也称为加载容量)。填充比必须介于0.0与1.0之间,它决定在散列集合向上调整大小之前,有多少能被充满。具体的说,就是当元素的个数大于散列集合容量乘以它的填充比时, 散列集合自动扩容(从新做一次散列运算,得到新空间的新位置,而不是把原来位置的对象直接照搬过来) 。对于没有获得填充比的构造函数,默认使用 0.75。HashSet没有定义任何超过它的超类和接口提供的其他方法。重要的是,注意散列集合并没有确保其元素的顺序,因为散列法的处理通常不让自己参与创建排序集合。如果需要排序存储,另一种类集 一一TreeSet将是一个更好的选择。注:HashMap底层也是用数组,HashSet底层实际上也是HashMap,HashSet类中有HashMap属性。HashSet实际上为(key.nuII)类型的HashMap。有key值而没有value值。即:HashMap有键-值两部分组成,而HashSet就是HashMap中的键的那一部分。所以HashMap和HashSet添加元素的规则是一样的。注意:HashMap中的put方法(相当于HashSet中的add方法):如果本来有一条记录:("zhangsan",20);再用put方法添加一条记录:put("zhangsan",28);那么会将zhangsan键与28值相关联,覆盖("zhangsan",20),返回20。而这样的情况在HashSet中就表现为把元素舍弃掉了。底层用的是哈希散列表(长度 16的数组)来存储对象,存放对象之前先做一个哈希散列运算(当要把对象放到到底层存储方式为哈希散列的集合中的时候,系统会自动调用hashcode方法):1、 首先得到对象的哈希码,就是用对象在内存中的的首地址调用hashCode()方法,不同对象的首地址是不同的。publicinthashCode();返回一个int值,也就是哈希码。还有Object类里toString方法默认返回的是:类名+@+地址,这里的地址也是用对象哈希码的16进制表示的。如果我们覆盖了hashcode方法,那么toString方法的返回值也将会跟这hashcode方法一起改变。API描述:publicStringtoString()返回该对象的字符串表示。通常, toString方法会返回一个"以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。Object类的toString方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于:getClass().getName()+@+Integer.toHexString(hashCode())hashCode()方法返回值的16进制形式,hashCode()方法返回的是对象的地址,是整型的。2、用hashCode()方法返回的哈希码对 HashSet底层数组的长度求余,得到一个 0-15之间的值(默认16个长度),然后这个值就是存在HashSet数组中的下标,如果该下标位置上已经有元素了,如果不冲突,就把这个对象放到该位置, 如果冲突的话,就对这两个对象作比较,如果不相等,就把这个对象也放到这个位置,对于是怎么放的, 有可能每个数组元素都是一个链表,那么是此下标的元素如果equals比较的结果不相等,就会都放到这个链表中。如果他们比较是相等的,那么这个要被插入的对象就被抛弃掉了,没有插入成功。HashSet比较两个对象是否相等用的是 equals()方法。所以,只有同时覆盖了对象的equals方法和hashCode方法,让此方法按自己的算法运算的话才能算是相同的对象,覆盖 hashCode方法的原则:原则1:让equals相等的对象返回相同的hashCode,这样用相同的哈希码得到的下标将会相同,使相同对象得到的下标冲突,这样就能过滤掉相等的元素。原则2:尽量保证(因为就算不同的对象,计算之后得到的下标也有可能相同) equals不相同的对象返回不同的hashCode(为了添加不同的元素)。原则3:尽量的让对象的哈希码随即散列。(不要发生局部聚集,使哈希码的取值范围尽量散列开来)TreeSetTreeSet实现了Set接口和SortedSet接口。使用元素的自然顺序对元素进行排序,或者根据创建set时提供的Comparator进行排序,具体取决于使用的构造方法。 (这里的自然顺序,是指该对象实现了 Comparable接口后定义的compareTo方

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论