当前位置: 首页 > news >正文

网站底部友情链接怎么做的域名与网站的区别

网站底部友情链接怎么做的,域名与网站的区别,百度软件优化排名,建设网站工作报告文章目录一 基础概念1 有关Java2 JVM / JDK / JRE3 与C的联系和区别4 各类型数据占用空间大小5 和 equals() 的区别、hashCode() 方法6 包装类型7 final 关键字8 参数传递机制#xff1a;值传递9 String 的内存情况10 访问修饰符11 引用拷贝、浅拷贝与深拷贝三 面向对象1 面向… 文章目录一 基础概念1 有关Java2 JVM / JDK / JRE3 与C的联系和区别4 各类型数据占用空间大小5 和 equals() 的区别、hashCode() 方法6 包装类型7 final 关键字8 参数传递机制值传递9 String 的内存情况10 访问修饰符11 引用拷贝、浅拷贝与深拷贝三 面向对象1 面向过程与面向对象2 构造方法3 OOP特性封装、继承、多态4 重载和重写5 继承重名问题6 继承实现原理7 继承的问题破坏封装8 类的扩展接口9 类的扩展抽象类10 类的扩展内部类7 代理模式四 异常1 异常分类2 try-catch-finally3 try-with-resources五 文件与 I/O 流1 transient 关键字2 文件类型文本文件和二进制文件3 文件读写4 Java I/O 流4.1二进制文件 - 字节流 - byte4.2 文本文件 - 字符流 - char六 反射1 动态语言2 什么是反射3 反射常用类与方法4 DEMO5 反射的应用JDK动态代理6 反射与泛型七 泛型1 概念和语法2 泛型擦除一 基础概念 1 有关Java Java是编译与解释并存的语言由 Java 编写的程序需要先经过编译步骤生成字节码文件.class 文件面向JVM而非特定系统的这种字节码必须由 Java 解释器来解释执行 编译型语言会通过编译器将源代码一次性翻译成可被该平台执行的机器码。一般情况下编译语言的执行速度比较快开发效率比较低解释型语言会通过解释器逐句的将代码解释为机器代码后再执行。解释型语言开发效率比较快执行速度比较慢 2 JVM / JDK / JRE 包含范围从大到小 JDKJava development kit功能齐全的 Java SDK。拥有 JRE 所拥有的一切还有编译器javac和工具如 javadoc 和 jdb。它能够创建和编译程序JREJava runtime environmentJava 运行时环境。它是运行已编译 Java 程序所需的所有内容的集合包括 Java 虚拟机JVMJava 类库java 命令和其他的一些基础构件。但是不能用于创建新程序JVMJava virtual machine运行 Java 字节码.class格式文件的虚拟机针对不同系统有不同的实现。JVM是一种规范满足规范的虚拟机都可称为JVM 3 与C的联系和区别 都是面向对象的语言支持封装、继承、多态Java 不提供指针来直接访问内存程序内存更加安全Java 的类是单继承的接口支持多重继承C 支持多重继承Java 有自动内存管理垃圾回收机制C 同时支持方法重载和操作符重载但是 Java 只支持方法重载 4 各类型数据占用空间大小 Java中比较特殊的是char类型占用2字节16bitchar 本质上是占用两个字节的无符号整数对应 Unicode 编号用于表示对应字符 5 和 equals() 的区别、hashCode() 方法 对于基本数据类型只能用 比较对于引用数据类型 用于比较内存地址 equals() 如果未被重写也是比较内存地址重写后按照指定规则判断两个对象是否相等重写 equals() 方法时必须同时重写 hashCode() 方法两个对象的 hashCode 值相等并不代表两个对象就相等哈希碰撞。两个对象相等则 hashCode 必相等两个对象的比较首先比较 hashCode() 的返回值是否相等如果不相等直接认为两个对象不相等如果相等则继续调用 equals() 方法返回 True 时视为两个对象相等如果重写 equals() 时没有重写 hashCode() 方法的话可能会导致 equals 方法判断是相等的两个对象hashCode 值却不相等hashCode() 存在的意义是减少 equals() 的调用提高执行速度 6 包装类型 包装类型的比较必须用 equals()基本数据类型存放在 Java 虚拟机栈中的局部变量表中而包装类型属于对象类型存在于堆中包装类常量池技术 Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128127] 的相应类型的缓存数据Character 创建了数值在 [0,127] 范围的缓存数据Float,Double 没有实现常量池 装箱与拆箱装箱其实就是调用了 包装类的valueOf()方法拆箱其实就是调用了 xxxValue()方法 Integer i 10; //装箱等价于 Integer i Integer.valueOf(10) int n i; //拆箱int n i.intValue()7 final 关键字 被 final 关键字修饰的类不能被继承修饰的方法不能被重写修饰的变量是基本数据类型则值不能改变修饰的变量是引用类型则不能再指向其他对象 8 参数传递机制值传递 Java只存在值传递如果向方法传递引用类型则在方法中产生引用类型的堆中的地址的拷贝 public class Person {private String name;// 省略构造函数、GetterSetter方法 }public static void main(String[] args) {Person xiaoZhang new Person(小张);Person xiaoLi new Person(小李);swap(xiaoZhang, xiaoLi);System.out.println(xiaoZhang: xiaoZhang.getName());System.out.println(xiaoLi: xiaoLi.getName()); }public static void swap(Person person1, Person person2) {Person temp person1;person1 person2;person2 temp;System.out.println(person1: person1.getName());System.out.println(person2: person2.getName()); }输出 person1:小李 person2:小张 // 在swap方法中调换了person1和person2的指向 xiaoZhang:小张 xiaoLi:小李 // 在主方法中引用指向并未改变swap 方法的参数 person1 和 person2 只是拷贝的实参 xiaoZhang 和 xiaoLi 的地址因此 person1 和 person2 的互换只是拷贝的两个地址的互换不会影响到实参 xiaoZhang 和 xiaoLi另附验证代码 public class Main {public static void change(Person p) {//p new Person(更改后); // main打印结果是更改前p.name 更改后; // main打印结果是更改后直接更改了输入内存地址里的内容}public static void main(String[] args) {Person p_in new Person(更改前);change(p_in);System.out.println(p_in.name);} }class Person {public String name;public Person(String name) {this.name name;} } 9 String 的内存情况 参考 JVM 博客 String 类底层使用 char[] 存储String 不同实例化方式的内存对比 字符串拼接的内存情况 str_instance.intern() 将字符串 str 放到常量池中 10 访问修饰符 修饰符范围public无限制protected子类、当前包default当前包private仅限当前类 protected 由于其子类的可见性多用于模板模式 11 引用拷贝、浅拷贝与深拷贝 引用拷贝创建新的对象引用指向原来的对象浅拷贝浅拷贝会在堆上创建一个新的对象区别于引用拷贝的一点不过如果原对象内部的属性是引用类型的话浅拷贝会直接复制内部对象的引用地址也就是说拷贝对象和原对象共用同一个内部对象深拷贝 深拷贝会完全复制整个对象包括这个对象所包含的内部对象 三 面向对象 1 面向过程与面向对象 面向过程 面向过程性能比面向对象高。 因为类调用时需要实例化开销比较大比较消耗资源所以当性能是最重要的考量因素的时候比如单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发面向对象 面向对象易维护、易复用、易扩展。 因为面向对象有封装、继承、多态性的特性所以可以设计出低耦合的系统使系统更加灵活、更加易于维护 2 构造方法 类默认具有不带参数的构造方法如果添加了类的构造方法无论是否有参Java 就不会再添加默认的无参数的构造方法了 无论是否用到要把无参的构造方法写出来原因如果子类构造方法没有显式地调用 super 构造器则默认调用 super() 子类调用父类的构造方法使用 super(...)且必须在子类构造方法的首行调用构造方法不能重写但是可以重载通过子类构造器创建对象时一定会直接或间接地调用父类的构造器直到调用了 Object 类的构造器且父类的构造方法先于子类执行 3 OOP特性封装、继承、多态 封装封装是指把一个对象的状态信息也就是属性隐藏在对象内部不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性继承继承是使用已存在的类的定义作为基础建立新类的技术新类的定义可以增加新的数据或新的功能也可以用父类的功能但不能选择性地继承父类。子类拥有父类对象所有的属性和方法包括私有属性和私有方法但是父类中的私有属性和方法子类是无法访问只是拥有多态编译时类型和运行时类型不一致具体表现为父类的引用指向子类的实例。引用类型变量发出的方法调用的到底是哪个类中的方法必须在程序运行期间才能确定多态不能调用“只在子类存在但在父类不存在”的方法尽管内存中加载了子类特有的属性和方法想要调用需要向下转型。多态情况下父类的方法称为虚拟方法调用方法的过程称为动态绑定 4 重载和重写 重载相同的方法名不同的参数列表。可以发生在一个类中也可以发生在父类和子类间。重载就是多个同名方法根据不同的传参来执行不同的逻辑处理。重载发生在编译时重写相同的方法名相同的参数列表。发生在父类和子类间。本质上是子类覆盖了父类的方法。重写发生在运行时具体要求 抛出异常的类型更小或相等访问权限更大或相等返回值的类型更小或相等如果方法的返回类型是 void 和基本数据类型则返回值重写时不可修改。但是如果方法的返回值是引用类型重写时可以返回该引用类型的子类 5 继承重名问题 如果重名的属性或方法是 private 修饰的则父类和子类互不影响 class Base {public static String s base_static_field;public String m base_nonstatic_field;public static void staticTest() {System.out.println(base: s);} }class Child extends Base {public static String s child_static_field;public String m child_nonstatic_field;public static void staticTest() {System.out.println(child: s);} }public class Verify {public static void main(String[] args) {Child child new Child(); // 该对象具有两个声明为 public 的属性 mBase base child;// 子类通过类型转换得到的父类System.out.println(Base.s);Base.staticTest();System.out.println(base.m);// 子类System.out.println(Child.s);Child.staticTest();System.out.println(child.m);} }输出结果 base_static_field base: base_static_field base_nonstatic_fieldchild_static_field child: child_static_field child_nonstatic_field6 继承实现原理 类加载时需要执行的代码执行顺序和代码顺序有关 静态代码块静态变量声明时的赋值 创建对象时需要执行的代码粗体执行顺序和代码顺序有关构造方法最后执行 非静态代码块非静态变量声明时的赋值构造方法 寻找要执行的实例方法时从对象的实际类型开始查找找不到的时候从父类递归查找 例如调用 base.func() 时过程如下 base 的实际类型为 Child在 Child 中找不到 func()从父类 Base 查找Base 包含 func()开始执行func() 调用 test()在 Child 中找到 test() 执行并返回到 func()func() 返回执行完成 构造场景如下 public class Verify {public static void main(String[] args) {// 创建子类对象Child child new Child();// 强转为父类并调用方法Base base child;base.func();} }class Base {static {System.out.println(base static block);}{System.out.println(base nonstatic block);}public Base() {System.out.println(base constructor);}public void func() {test();}public void test() {System.out.println(base method call);} }class Child extends Base {static {System.out.println(child static block);}{System.out.println(child nonstatic block);}public Child() {System.out.println(child constructor);}Overridepublic void test() {System.out.println(child method call);} }输出结果 base static block // 1.父类加载 child static block // 2.子类加载 base nonstatic block base constructor // 3.执行父类实例化代码 child nonstatic block child constructor // 4.执行子类实例化代码至此完成子类对象创建child method call // 调用的是子类而非父类的test()7 继承的问题破坏封装 使用继承时必须严格符合 is-a 的关系否则会造成混乱 例如“鸟类”作为父类拥有“可以飞”的方法“企鹅”作为子类就是一种不好的实现 子类继承父类时如果不知道父类的实现细节就无法正确地进行扩展 解决方法 使用 final 避免继承 被 final 修饰的方法父类拥有随意修改方法内部实现的自由被 final 修饰的类由于无法被继承其实现是自由的 使用组合 接口将父类对象作为子类的一个属性同时保证父类和子类的一致性 interface Add {void plusOne(); }class Base implements Add {Overridevoid plusOne() {// ...} }class Child implements Add {Base b;Overridevoid plusOne() {b.plusOne();// 方法扩展...} }8 类的扩展接口 接口声明了一组能力但它自己没有对这些能力做出实现仅是一个约定 继承要求子类和父类间存在 is-a 的关系而接口关注的是具有某种能力 is-able-to在某些情况下代码只关注一个类是否具有某个能力而不关注具体类型面向接口编程可以实现高效的代码复用 接口的一个重要功能是降低了耦合 使用接口的程序依赖于接口本身而非实现接口的具体类型可以灵活替换接口实现而不影响接口使用 接口可以有变量必须且默认被 public static final 修饰接口可以多继承类也可以实现多个接口和类一样接口可以使用 instanceof 判断某个类是否实现了某个接口JDK8和9的接口增强接口内可以定义静态方法和默认方法 引入默认方法的目的是方便给现有的类增加新方法将新增方法设置为 default现有的接口实现类无需实现默认方法 public interface Demo {// 普通方法声明void hello();// 静态方法public static void hola() {System.out.println(hola);}// 默认方法default void hi() {System.out.println(hi);} }9 类的扩展抽象类 接口声明能力抽象类提供默认实现实现全部或部分方法方便子类实现接口一个接口经常有一个对应的抽象类抽象类可以定义实例变量而接口不可以抽象类有构造方法但是不能被实例化 10 类的扩展内部类 内部类只是编辑器的概念对JVM而言每个内部类都会被编译成一个独立的类生成独立的字节码文件四种内部类 静态内部类 与外部类关系密切且不依赖于外部类实例对于外部类只能访问外部类的静态属性和方法包含 private静态内部类的方法可以设置为静态也可以非静态但都只能访问外部类的静态属性和方法 成员内部类 对于外部类可以访问外部类的静态和非静态的成员和方法包含 private成员内部类对象总是和一个外部类对象相连 成员内部类中不能定义静态的属性和方法需要先创建外部类对象再创建内部类对象 一种应用场景是外部类的方法返回值是某个接口使用 private 的内部类实现该接口并在方法中返回此时的接口实现对外完全隐藏 方法内部类 应用场景和成员内部类相似可以由成员内部类代替如果某个类只在某个方法中被使用用方法内部类的封装性更好方法可以是静态的也可以是非静态的对方法内部类的区别在于能否访问外部类的非静态属性方法内部类可以访问 final 修饰的方法参数和局部变量 匿名内部类 public class Verify {public static void main(String[] args) {// 1.静态内部类// 实例化静态内部类调用其非静态方法仅能访问外部类的静态属性Outer.StaticInner staticInner new Outer.StaticInner();staticInner.accessOuterStaticField();// 如果暴露的方法是静态方法则无需创建对象即可执行Outer.StaticInner.accessOuterStaticFieldByStaticMethod();// 2.成员内部类// 实例化非静态内部类并调用其方法访问外部类的所有属性Outer.NonStaticInner nonStaticInner new Outer().new NonStaticInner();nonStaticInner.accessAllOuterField();// 3.方法内部类new Outer().getInstance(param);} }class Outer {// 外部静态属性private static String outerStaticField outerStaticField;// 外部非静态属性private String outerNonStaticField outerNonStaticField;// 外部静态方法private static void outerStaticMethod() {System.out.println(outerStaticMethod);}// 外部非静态方法private void outerNonStaticMethod() {System.out.println(outerNonStaticMethod);}// 1.静态内部类static class StaticInner {public void accessOuterStaticField() {System.out.println(StaticInner-NonStaticMethod);outerStaticMethod(); // 访问外部静态方法System.out.println(outerStaticField); // 访问外部静态属性}public static void accessOuterStaticFieldByStaticMethod() {System.out.println(StaticInner-StaticMethod);outerStaticMethod(); // 访问外部静态方法System.out.println(outerStaticField); // 访问外部静态属性}}// 2.非静态内部类class NonStaticInner {public void accessAllOuterField() {System.out.println(NonStaticInner);outerStaticMethod(); // 访问外部静态方法outerNonStaticMethod(); // 访问外部非静态方法System.out.println(outerStaticField); // 访问外部静态属性System.out.println(outerNonStaticField); // 访问外部非静态属性}}// 3.方法内部类SomeAbility getInstance(final String param) {final String localParam localParam;class MethodInner implements SomeAbility {// 接口实现...public MethodInner() {System.out.println(MethodInner);System.out.println(param);System.out.println(localParam);}}return new MethodInner();} }7 代理模式 静态代理 静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。通过代理类屏蔽对目标对象的访问并且可以在目标方法执行前后做一些自己想做的事情。静态代理的实现步骤定义一个接口及其实现类 创建一个代理类同样实现这个接口将目标对象注入进代理类使其成为代理类的成员变量然后在代理类的对应方法调用目标类中的对应方法。静态代理中对目标对象的每个方法的增强都是手动完成的非常不灵活比如接口一旦新增加方法目标对象和代理对象都要进行修改且麻烦(需要对每个目标类都单独写一个代理类)。 JDK动态代理反射的应用 动态代理在运行时动态生成类字节码并加载到 JVM 中的。动态代理更加灵活不需要必须实现接口可以直接代理实现类并且可以不需要针对每个目标类都创建一个代理类。“一个代理类完成全部的代理功能”。 使用实例 接口与接口的实现 interface Human{String getBelief();void eat(String food); }class SuperMan implements Human{Overridepublic String getBelief() {return I believe I can fly!;}Overridepublic void eat(String food) {System.out.println(我喜欢吃 food);} }动态代理类动态代理对象调用原生方法的时候最终实际上调用到的是 invoke() 方法然后 invoke() 方法调用了被代理对象的原生方法。 import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;public class DebugInvocationHandler implements InvocationHandler {// 代理类中的真实对象private final Object target;public DebugInvocationHandler(Object target) {this.target target;}/*** 动态代理的核心部分* proxy :动态生成的代理类* method : 与代理类对象调用的方法相对应* args : 当前 method 方法的参数**/public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {//额外操作...Object result method.invoke(self.target, args); //调用的是method的invoke方法//额外操作...return result;} }获取代理对象的工厂类输入需要被代理的对象输出其代理。即根据对象实例建立代理实例。 public class JdkProxyFactory {public static Object getProxy(Object target) {return Proxy.newProxyInstance(target.getClass().getClassLoader(), // 目标类的类加载target.getClass().getInterfaces(), // 代理需要实现的接口可指定多个new DebugInvocationHandler(target) // 代理对象对应的自定义 InvocationHandler);} }实际使用一个代理到处使用 public static void main(String[] args) {//被代理的类型1SuperMan superMan new SuperMan();Human proxyInstance (Human) ProxyFactory.getProxyInstance(superMan); // 强转为对应接口的类型// invoke() 方法: 当我们的动态代理对象调用原生方法的时候最终实际上调用到的是 invoke() 方法然后 invoke() 方法代替我们去调用了被代理对象的原生方法。String belief proxyInstance.getBelief();proxyInstance.eat(四川麻辣烫);//被代理的类型2NikeClothFactory nikeClothFactory new NikeClothFactory();ClothFactory proxyClothFactory (ClothFactory); ProxyFactory.getProxyInstance(nikeClothFactory);proxyClothFactory.produceCloth();}四 异常 1 异常分类 在编译过程中如果受检查异常没有被 catch/throw 处理的话就无法通过编译未受检异常表示编程时的逻辑错误应该修改逻辑而非进行异常处理受检异常表示程序本身没有问题由于一些不可预测的错误导致的异常 2 try-catch-finally try 用于捕获异常其后可接零个或多个 catch 块如果没有 catch则必须有 finally catch 用于处理 try 捕获到的异常 finally 无论是否捕获或处理异常finally 都会被执行当在 try 或 catch 中返回时finally 将在方法返回之前被执行但不会改变返回值 static int finallyTest() {int i 1;try {return i;} finally {i;} } // 返回结果是1而不是2 // 因为执行到 try 内的返回语句时会将返回值保存在临时变量中然后执行 finally // 返回的是临时变量而非修改后的值只要 finally 语句中有返回语句finally 语句的内容将被执行而不是 try 或 catch 的返回语句这样会掩盖原返回值或异常避免在 finally 中返回或抛出异常 3 try-with-resources 在 try 后增加括号在其中创建资源对象任何实现 java.lang.AutoCloseable 或者 java.io.Closeable 的对象不必显式关闭 try (BufferedInputStream bin new BufferedInputStream(new FileInputStream(new File(test.txt)));BufferedOutputStream bout new BufferedOutputStream(new FileOutputStream(new File(out.txt)))) {int b;while ((b bin.read()) ! -1) {bout.write(b);}}catch (IOException e) {e.printStackTrace();}五 文件与 I/O 流 1 transient 关键字 作用是阻止实例中那些用此关键字修饰的变量被序列化 当对象被反序列化时被 transient 修饰的变量值不会被持久化和恢复transient 只能修饰变量不能修饰类和方法transient 修饰的变量在反序列化后变量值将会被置成类型的默认值静态变量因为不属于任何对象所以无论有没有 transient 关键字修饰均不会被序列化 2 文件类型文本文件和二进制文件 文本文件的每个二进制字节都是某个可打印字符的一部分都可以用最基本的文本编辑器查看和编辑二进制文件中每个字节不一定表示字符可能表示颜色、字体等如果用基本的文本编辑器直接查看一般是乱码 3 文件读写 操作系统和硬盘交互时一般按块批量传输以均摊延时开销一般读写文件需要两次复制 读文件硬盘 - 操作系统内核 - 应用程序内存 操作系统在操作文件时一般有打开和关闭的概念 打开文件会在操作系统内核建立一个有关该文件的内存结构这个结构一般通过一个整数索引引用这个索引被称为文件描述符操作系统能同时打开的文件数是有限的所以在不使用文件时要关闭 4 Java I/O 流 Java 具有很多面向流的方法接受的参数和返回的方法都是流接口对象面向接口编程类似容器类的协作体系一些实际上不是 IO 的数据也或目的地的对象也可以转换为流以使用流的方法例如字节数组可以包装为 ByteArrayInputStream 和 ByteArrayOutputStream序列化和反序列化 序列化就是将内存中的 Java 对象持久地保存到一个流中反序列化就是从流中恢复 Java 对象到内存作用对象的持久化网络远程调用通过接口 Serialzable 标记对象是可序列化的常见的序列化方式JSON、ProtoBuf 4.1二进制文件 - 字节流 - byte InputStream/OutputStream 基类抽象类 abstract class InputStream ... {// 阻塞直到读取下一个字节public abstract int read() throws IOException// 阻塞直到读取若干字节将读到的字节放入参数数组b中public abstract int read(byte[] b) throws IOExceptionpublic abstract int read(byte[] b, int off, int len) throws IOException }abstract class OutputStream ... {// 向流中写入一个字节仅写入b最低的8位public abstract void write(int b) throws IOException// 批量写入public abstract void write(byte[] b) throws IOExceptionpublic abstract void write(byte[] b, int off, int len) throws IOException// 将缓冲数据写入默认实现只是将数据传递给操作系统实际写入时机由操作系统决定public void flush() throws IOException }FileInputStream/FileOutputStream 输入源和输出目标是文件 class FileInputStream extends InputStream ... {// 构造方法public FileInputStream(File file) throws FileNotFoundExceptionpublic FileInputStream(String name) throws FileNotFoundException }class FileOutputStream extends OutputStream ... {// 构造方法public FileOutputStream(File file, boolean append) throws FileNotFoundExceptionpublic FileOutputStream(String name) throws FileNotFoundException }ByteArrayInputStream/ByteArrayOutputStream 输入源和输出目标是字节数组 class ByteArrayInputStream extends InputStream ... {// 构造方法适配器模式将字节数组包装为一个输入流public ByteArrayInputStream(byte[] buf)public ByteArrayInputStream(byte[] buf, int offset, int length) }class ByteArrayOutputStream extends OutputStream ... {// 构造方法底层数组大小会根据数据内容动态扩展public ByteArrayOutputStream()public ByteArrayOutputStream(int size)// 将数据转换为其它类型public synchronized byte[] toByteArray()public synchronized String toString()public synchronized String toString(String charsetName)// 写入另一个输出流public synchronized void writeTo(OutputStream out) throws IOException }// 使用 ByteArrayOutputStream 读文件 public static void main(String[] args) {InputStream input new FileInputStream(hello.txt);try {ByteArrayOutputStream output new ByteArrayOutputStream();byte[] buf new byte[1024];int bytesRead 0;while ((bytesRead input.read(buf)) ! -1) { // 从文件输入流读取数据output.write(buf, 0, bytesRead); // 将读到的数据写入字节数组输出流}String data output.toString(UTF-8); // 将字节数组输出流转换为字符串} finally {input.close();} }DataInputStream/DataOutputStream 以非字节为单位进行读写 是装饰器基类 FilterInputStream/FilterOutputStream 的子类构造时均需要传入 InputStream/OutputStream 对象 BufferedInputStream/BufferedOutputStream 添加缓冲区 使用 FileInputStream/FileOutputStream 时应该总是使用缓冲区包装InputStream input new BufferedInputStream(new FileInputStream(hello.txt)); 4.2 文本文件 - 字符流 - char 对于文本文件字节流没有编码的概念并且不能按行处理字符流是按 char 读取的对于绝大部分字符一个字符对应一个 char对于增补集的字符需要两个 char 表示Reader/Writer 基类抽象类InputStreamWriter/OutputStreamWriter 适配器类将 InputStream/OutputStream 转换为 Reader/Writer public static void main(String[] args) {// 输出字节流转换为字符流Writer writer new OutputStreamWriter(new FileOutputStream(hello.txt), GB2312);try {writer.write(hello)} finally {writer.close();} }FileReader/FileWriter 不能指定编码类型只能使用默认编码如果需要指定编码使用InputStreamWriter/OutputStreamWriterCharArrayReader/CharArrayWriter 输入源和输出目标是字符数组StringReader/StringWriter 本质同上因为字符串底层是字符数组BufferedReader/BufferedWriter 装饰类为 Reader/Writer 提供缓冲 六 反射 1 动态语言 动态语言指运行时可以改变其结构的语言例如新的函数、对象、甚至代码可以被引进已有的函数可以被删除或是其他结构上的变化反射机制使得Java成为了“准动态语言”加载完类之后在堆内存的方法区中就产生了一个Class类型的对象一个类只有一个Class对象这个对象就包含了完整的类的结构信息 2 什么是反射 在运行状态中对于任意一个类都能够知道这个类的所有属性和方法对于任意一个对象都能够调用它的任意方法和属性并且能改变它的属性反射机制允许程序在运行时取得任何一个已知名称接口、类或实例的内部信息包括包括其修饰符、属性、方法、接口等并可于运行时改变属性值或调用方法反射并不是优先选项 反射容易出现运行时错误因为编译器无法协助类型检查反射的性能更低如果能用接口实现同样目的优先选择接口 3 反射常用类与方法 java.lang.Class: 代表一个类 获取 Class 实例不能使用 new而应该通过 类名.class 或 实例.getClass() 获得 对应关系 Class类Class实例实例运行时类实例public static void main(String[] args) {// 同一个类的不同实例对应的 Class 实例 是同一个Person p1 new Person(1号);Person p2 new Person(2号);Class c1 p1.getClass();Class c2 p2.getClass();Class c3 Person.class;System.out.println(c1 c2); // trueSystem.out.println(c1 c3); // true// 数组的元素类型与维度一维数组二维数组等一样对应的 Class 实例 是同一个Class c4 new String[10].getClass();Class c5 new String[8].getClass();Class c6 new int[10].getClass();Class c7 String[].class;System.out.println(c4 c5); // trueSystem.out.println(c4 c6); // falseSystem.out.println(c4 c7); // true}java.lang.reflect.Method: 代表类的方法java.lang.reflect.Field: 代表类的属性java.lang.reflect.Constructor: 代表类的构造器 4 DEMO package com.ys.reflex; public class Person {// 私有属性private String name Tom;// 公有属性public int age 18;// 构造方法public Person() {}// 私有方法private void say(){System.out.println(private say()...);}// 公有方法public void work(){System.out.println(public work()...);} }获取 Class 对象的三种方式 // 1.通过对象调用 getClass() 方法来获取Person p1 new Person();Class c1 p1.getClass();// 2.直接通过 类名.class 的方式得到,该方法最为安全可靠程序性能更高Class c2 Person.class;// 3.通过 Class 对象的 forName() 静态方法来获取但可能抛出 ClassNotFoundException 异常Class c3 Class.forName(com.ys.reflex.Person);Class 类具有如下的方法 getName()获得类的完整名字 getFields()获得类的 public 类型的属性getDeclaredFields()获得类的所有属性包括 private 声明的和继承父类的属性getMethods()获得类的 public 类型的方法getDeclaredMethods()获得类的所有方法包括 private 声明的和继承父类的方法getMethod(String name, Class[] parameterTypes)获得类的特定方法name 参数指定方法的名字parameterTypes 参数指定方法的参数类型getConstructors()获得类的public类型的构造方法getConstructor(Class[] parameterTypes)获得类的特定构造方法parameterTypes 参数指定构造方法的参数类型newInstance()通过类的无参构造方法创建这个类的一个对象 运行时类必须提供空参的构造器空参的构造器的访问权限足够 写代码时总是要提供一个 public 的空参构造器原因 便于通过反射创建运行时类的对象便于子类继承此运行时类时默认调用 super() 时保证父类有此构造器 public void test2() throws Exception{Class clazz Person.class; // 获取Class对象// 1.通过反射创建Person类的对象Constructor cons clazz.getConstructor(String.class,int.class); // 获取指定构造器Object obj cons.newInstance(Tom, 12); // 创建对象Person p (Person) obj;// 2.通过反射调用对象指定的属性、方法// 访问并修改属性Field age clazz.getDeclaredField(age);age.set(p, 10);// 调用方法Method show clazz.getDeclaredMethod(show);show.invoke(p); // 调用私有构造器Constructor cons1 clazz.getDeclaredConstructor(String.class);cons1.setAccessible(true);Person p1 (Person) cons1.newInstance(Jerry);// 访问并修改私有属性Field name clazz.getDeclaredField(name);name.setAccessible(true);name.set(p1, HanMeimei);// 调用私有方法Method showNation clazz.getDeclaredMethod(showNation, String.class);showNation.setAccessible(true);String nation (String) showNation.invoke(p1, 中国);// 调用静态私有方法Method showDesc clazz.getDeclaredMethod(showDesc);showDesc.setAccessible(true);Object returnVal showDesc.invoke(null);}5 反射的应用JDK动态代理 动态代理详细参考 6 反射与泛型 在 Class 对象中包含泛型信息 public class MyGeneticClassK extends ComparableK, V {K key;V value;ListString list;public V test(List? extends Number numbers) {return null;}public static void main(String[] args) throws Exception {ClassMyGeneticClass c MyGeneticClass.class;// 获取类定义的泛型和边界for (TypeVariable t : c.getTypeParameters()) {System.out.println(genetic defined by class: t.getName() extends Arrays.toString(t.getBounds()));}// 属性的泛型for (Field field : c.getDeclaredFields()) {System.out.println(field: field.getGenericType());}// 方法泛型参数Method method c.getDeclaredMethod(test, new Class[]{List.class});System.out.println(method parameter: Arrays.toString(method.getGenericParameterTypes()));System.out.println(method return: method.getGenericReturnType());} }七 泛型 1 概念和语法 泛型的本质是参数化类型即数据类型被指定为一个参数 在指定类的泛型为某个参数时和类的实例有关因此静态方法不能使用类定义的泛型如果允许使用则对于每种实例化类型都有一份对应的静态属性和方法但从类型擦除的角度这些实例化的类型属于一个类这违反了静态的原则 静态属性和方法中不能使用类的泛型但静态方法可以自定义泛型成为泛型方法 泛型方法并不是“使用”了泛型的方法而是“定义”了新泛型的方法泛型方法可以用 static 修饰 // 类定义多个泛型 class GeneticBaseK, V {// 非静态属性可以使用类定义的泛型private K key;private V value;// 普通方法可以使用类定义的泛型public void commonMethod() {// 可以使用 K, V}// 非静态泛型方法可以使用类定义的泛型public T void nonstaticGeneticMethod() {// 可以使用 K, V, T}// 静态泛型方法不能使用类定义的泛型泛型类是和实例相关的public static E void staticGeneticMethod(E e) {// 可以使用 E} }基本类型不能用于实例化泛型参数如有需要选择包装类如果实例化泛型类时没有指定具体的类型则认为此泛型的类型为 Object继承泛型类时只需在 extends 后的父类后指明泛型类型即可 public class SubOrder extends OrderString 如果不指明则当前类仍然沿用泛型 public class ArrayListE extends AbstractListE 不能直接创建泛型对象和数组因为在编译时 T 不是一个具体的类无法通过编译 创建泛型类通过反射创建泛型数组一般而言泛型容器可以满足需求如果实在需要数组形式同样需要反射 2 泛型擦除 Java 的泛型是伪泛型在运行期间所有的泛型信息都会被擦掉想象运行时的代码将泛型括号划去容易理解很多问题将类型参数擦除替换为 Object并进行必要的强制类型转换从泛型擦除的角度理解类 A 是类 B 的父类GA 和 GB 二者不具备子父类关系而 AG 是 BG 的父类 // 由于泛型擦除不能定义如下的重载方法 public void test(MyGeneticClassInteger g); public void test(MyGeneticClassString g);// 另一种现象 MyGeneticInteger i new MyGenetic(1); MyGeneticString s new MyGenetic(a); i.getClass() MyGenetic.class; // true s.getClass() MyGenetic.class; // true// 不支持如下写法 i instanceof MyGeneticInteger// 同样不支持如下写法 class Base implements ComparableBase {...} class Child extends Base implements ComparableChild {...} // 错误接口不能被实现多次 // 想改变子类的比较方法只能Override class Child extends Base {Overridepublic int compareTo(Base o) {if (!o instance of Child) {throw new IllegalArgumentException();}Child c (Child) o;// ...} }
http://www.yutouwan.com/news/65680/

相关文章:

  • 西安企业网站建设模板国外网站网页设计
  • a4网站建设阿里云个人网站建设书
  • 好用的手机网站主页淄博网站建设与推广
  • 上海模板开发建站wordpress在新窗口打开
  • 游戏网站建设表格台州汇客网站建设
  • 青岛装饰公司十强排名网络优化的目的
  • 网站服务器怎么进做网站用旧域名好不好
  • 快速域名网站备案免费制作图片生成器
  • 网站开发 浏览器兼容性正规漫画网站开发流程
  • 建设团购网站河南政务服务网查二建证书
  • 网上哪里给公司做网站wordpress 页面 html代码
  • 有教做鱼骨图的网站吗房产网签是什么意思
  • 电子商务网站建设与管理的实践报告网页设计与制作教程免费
  • 大数据技术建设网站设计平面创意
  • 大航母网站建设好不好无为住建设局网站
  • 网站需要怎么做的吗营销传播策略
  • 网站标准规范建设佛山微信网站开发
  • 做301网站打不开网站建设最重要的环节
  • 成都网站建设开发公司哪家好网站建设技术大全
  • 做百度网上搜索引擎推广最好网站做百度网站图片怎么做
  • 个人网站的成本html怎么做网站版块
  • 互联网公司怎么找网站建设客户阿里云apache重写wordpress
  • 泗洪网站建设怎样免费个人网站建设
  • 网站建设方案书阿里云备案找能做网站的
  • 电商网站前端制作分工东莞在哪里学网站建设
  • dz整站网站建设百度关键词搜索排行
  • 建设门户网站需要注意什么建立企业网站流程
  • 体检营销型网站福州建设招聘信息网站
  • 成都网站制作推来客网站系统情侣手表网站
  • qq上网站做我女朋友记事本做网站表格