知识点总结:Java核心技术(卷1)

java核心技术卷1基础知识整理 这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mar 阅读详情

Java核心技术(卷1)

一、基础概念

1.1 基本程序设计结构

  • 1.1 数据类型

    • 1.1.1 数值类型

      • 1️⃣从java7开始,加上前缀0b或0B就可以写二进制;

      • 2️⃣指数的表示

        • 十进制中以10为底指数的表示:

          • double d = 1.0e+4; // 10000.0
          • double d2 = 100000.0e-4; // 10.0
        • 十六进制中以2位底指数的表示:

          • double a1 = 0x1.0p+3; // 8.0
          • double a2 = 0x1.0p-3; // 0.125
      • 3️⃣double中的严格浮点计算:strictfp

        • double类型使用64位存储一个数值,而有些处理器使用80位浮点寄存器。这些寄存器增加了中间过程的计算精度(将中间结果存储在80位寄存器中,将最终结果截断位64位)。这个过程增加了计算精度,但结果可能与始终在64位机器上计算的结果不一样。
        • 如果将一个类标记为strictfp,那么这个类的所有方法都要使用严格的浮点计算。
        • 严格浮点计算:所有的中间计算必须进行截断。
        • 默认情况下是不采用严格的浮点计算。
      • double类型的三个特殊值:增无穷大、负无穷大、NaN

        • Double.POSITIVE_INFINITY // 正无穷大

        • Double.NEGATIVE_INFINITY // 负无穷大

        • Double.NaN

          • 检查一个字符是否为数值:Double.isNaN(x)
    • 1.1.2 Unicode和char类型

      • Unicode

        • 专业术语

          • 码点:某个字符所对应的代码值;
          • Unicode中码点的表示:Unicode的码点可以分为17个级别,第一个级别,码点从U+0000到U+FFFF,被称为基本的多语言级别,其中包括经典的Unicode代码;其余的16个级别的码点从U+10000到U+10FFFF,其中包括一些辅助字符。
          • 代码单元:用8位或16位(UTF-8是8位表示,UTF-16用16位表示)字节来表示Unicode中基本的多语言级别,被称之为代码单元。也就是说,UTF-8中代码单元是8位字节,UTF-16中代码单元是16位字节。
        • UTF-16编码采用不同长度的编码表示所有的Unicode码点

          • 在UTF-16中,表示一个Unicode码点,需要一个或两个代码单元。
      • char类型

        • 在java中,char类型描述了UTF-16的一个代码单元

          • 因此,“char用来表示单个字符”的说法不完全正确。
        • char类型是用16位表示

        • 有些unicode字符可以用一个char值来描述,另一些Unicode字符需要用两个char值来描述。

      • 区分码点、代码单元的用途:

        • length() 方法

          • length方法将返回UTF-16编码表示的给定字符串所需要的代码单元数量。
        • 想要获取实际长度,即码点数量,即字符个数

          • String greeting = “hello”;
            int cpCount = greeting.codePointCount(0, greeting.length());
        • 获取第几个代码单元:

          • String greeting = “hello”;
            char first = greeting.atChar(0);
        • 获取第几个码点:

          • String greeting = “hello”;
            // i 为第i个码点,i从0开始
            int index = greeting.offsetByCodePoints(0, i);
            greeting.codePointAt(index);
    • 1.1.3 大数值: BigInteger和BigDecimal

      • BigInteger可以实现任意精度的整数运算;
        BigDecimal可以实现任意精度的浮点运算;
  • 1.2 规范

    • 1.2.1 变量

      • 关于“$”

        • 尽管$是一个合法的Java字符,但不要在自己的编码中使用这个字符,它只用在Java编译器或其他工具生成的名字中。
      • 关于“++”的使用

        • 建议不要在代码中使用“++”,这样的代码很容易让人困惑,而且会带来烦人的bug。
  • 1.3 运算符

    • 1.3.1 位运算符

      • 和<<运算符将位模式左移或右移

      • 运算符会用0填充高位;>> 会用符号位填充高位;不存在<<< 运算符;

      • 位运算符的右操作数要完成模32的运算(除非左操作数是long类型,这种情况下需要对右操作数模64):1<<35 等于1<<3 等于8
    • 1.3.2 运算符的级别

      • &&的优先级比|| 的优先级高
      • += 是右结合运算符,所以表达式: a+=b +=c 等价于: a+=(b+=c)
  • 1.4 String

    • 1.1 String是不可变字符串。一定不要使用“==”检测两个字符串是否相等,每次连接字符串,都会构建一个新的String对象;

      每次连接都会创建一个新的字符串,这样既耗时,又浪费空间。使用StringBuilder类就可以避免这个问题的发生。

      StringBuilder的前身是StringBuffer。StringBuffer效率稍微有些低,但允许采用多线程的方式执行添加或删除字符的操作。

      StringBuilder 除了能够apped字符串,还能添加代码单元,添加码点

      所有字符串都在一个单线程中编辑,则应该用StringBuilder代替它。

      • 编译器可以让字符串共享。如果虚拟机使用让字符串共享就可以使用“==”运算符检测两个字符串是否相等。但,实际上只是字符串常量可以共享,而+或substring等操作产生的结果并不共享。
      • “==”运算符能够用来确定两个字符串是否放在同一个位置。如果两个字符串放在同一个位置,它们必然相等。完全有可能将相同内容的字符串放在不同的位置上。
      • 使用equals 方法比较两个字符串是否相等。
    • 1.2 String 的length方法将返回采用UTF-16编码表示的给定字符所需要的代码单元数量

      • 要想获取实际的字符长度,即码点数量,可以调用:codePointCount 方法

      • public static void test04() throws UnsupportedEncodingException {
        String greeting = “Hello”;
        String codeStr = “\uD835\uDD46”;
        byte[] b = codeStr.getBytes(“UTF-16”);
        String s = new String(b, “UTF-16”);
        System.out.println(“greeting:”+greeting);
        System.out.println(“一个UTF-16编码的特殊符号s:”+s);
        System.out.println("greeting.length() : " + greeting.length()); // 打印出 5
        System.out.println("greeting.codePointCount() : " + greeting.codePointCount(0, greeting.length())); // 打印出5
        System.out.println("s.length() : " + s.length()); // 打印出 2
        System.out.println("s.codePointCount() : " + s.codePointCount(0, s.length())); // 打印出 1
        }

        • greeting:Hello
          一个UTF-16编码的特殊符号s:?
          greeting.length() : 5
          greeting.codePointCount() : 5
          s.length() : 2
          s.codePointCount() : 1
    • 1.3 连接字符串:join 方法,可以指定分界符

    • 1.4 所有字符串都属于CharSequence接口

  • 1.5 控制流程

    • “break 和 跳出标签”的用法:可以将标签应用到任何语句中,甚至可以应用到if语句或块语句中
  • 1.6 数组

1.2 对象和类

  • 类

    • 在一个源文件中,只能有一个共有类,但可以有任意数目的非公有类。

    • 构造器

      • 构造器与类同名
    • finalize方法

      • 可以为任何一个类添加finalize方法。finalize方法将在垃圾回收器清楚对象之前调用(但是很难知道这个方法什么时候才能被调用)。
  • 对象

    • Java的对象都是在堆中创造;

    • ⚠️警告:不要编写返回引用可变对象的访问器方法。如果需要返回一个可变对象的引用,应该首先对它进行克隆(clone)。

      • // 错误代码示例
        /**
  • Date对象有一个更改器方法setTime。

  • 也就是说Date对象是可变的,这一点就破坏了

  • 封装性!
    */
    public Date gethireDay(){
    return this.hireDay;
    }
    - // 正确的做法
    public Date getHireDay(){
    return (Date)this.hireDay.clone();
    }

    • 封装:

      • 封装通常提供三项内容:

        • 一个私有的数据域;
        • 一个公有的域访问器方法;
        • 一个公有的域更改器方法;
      • 封装的好处:

        • 1️⃣可以改变内部实现;
        • 2️⃣更改器方法可以执行错误检查;
      • 警告:永远不要编写返回引用 可变对象 的方法器方法。

        • 如果要返回一个可变对象的引用,首先对其进行克隆,否则将破坏封装性;
        • 例如:
          LocalDate类没有更改器方法;
          Date对象是可变的
    • 调用构造器的具体处理步骤:

      • 0、静态域在类被加载的时候进行初始化。静态代码块在类第一次的时候执行一次。(创建对象的时候不再执行)

      • 1、所有数据域被初始化为默认值(0、false、或null);

      • 2、按照在类声明中出现的顺序,依次执行所有域初始化语句和初始化块;

        • 对于类的静态域进行初始化的代码比较复杂,可以使用静态的初始化块;
      • 3、如果构造器第一行调用了第二个构造器,则执行第二个构造器主体;

      • 4、执行这个构造器的主体;

  • 修饰符:

    • final 实例域

      • 可以将实例域声明为final,在构造对象的时候必出初始化这样的域;
      • final修饰符大都应用于基本(primitive)类型域,或不可变(immutable)类的域。对于可变的类,使用final修饰可能会对读着造成混乱
      • final 修饰的类不允许被继承;final修饰的方法不允许被覆盖;
      • 如果将一个类声明为final,只有其中的方法自动地成为final,而不包括域;
    • static 方法

      • 建议使用类名而不是对象名来调用静态方法,因为静态方法和对象没有任何关系。
      • 静态方法的另一种常见用途是使用静态工厂方法来构造对象。
  • 静态导入(import)

    • import语句不仅可以导入类,还增加了导入静态方法和静态域的功能
  • 其他

    • 编译运行带有包的源文件

      • 编译器在编译源文件的时候不检查目录结构,如果它不依赖其他包就不会出现编译错误。但如果编译后的类文件没有在声明的包下,程序最终无法运行。
    • 类路径

      • 类文件可以存储在JAR文件中。使用jar文件需要设置classpath
    • 文档注释:javadoc -d docDirectory nameofPackage1 nameofPackage2 ……

  • Java用于控制可见性的4个修饰符:

    • private 仅对本类可见;

    • public 对所有类可见;

    • protected 对本包和所有子类可见;

      • 如果子类和父类不再同一个包下,应当用子类对象访问父类protected方法;
    • 默认,不需要修饰符 对本包可见;

  • 类的加载:

    • 在启动时,包含main方法的类被加载。它会加载所需要的类。这些被加载的类又要加载它们需要的类,依次类推。

      对于一个大型的应用,可以使用技巧给用户一个启动速度比较快的幻觉:
      1、确保包含main方法的类没有显式地引用其他类;
      2、显示一个启动画面;
      3、通过调用Class.forName手工加载其他的类;

1.3 继承

  • 继承是Java的核心技术

  • super和this

    • 有些人认为super与this引用是类似的概念,实际上这样的比较并不恰当。因为super并不是一个对象的引用,不能讲super赋给另一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字。

    • this的用途

      • 1、引用隐式参数;
      • 2、调用该类的其他的构造器;
    • super的用途

      • 1、调用超类的方法;
      • 2、调用超类的构造器;
  • 子类和超类

    • 子类

      • 子类构造器

        • 使用super调用构造器的语句必须是子类构造器的第一条语句;
        • 如果子类构造器没有显式调用超类构造器,将自动地调用该超类的默认构造器(没有参数的构造器)
        • 如果子类构造器没有显式的调用超类构造器,超类又没有不带参数的构造器,Java编译器将报告错误
    • 类型转化

      • 只能在继承层次内进行类型转化;
      • 在将超类转化为子类之前,应该使用instanceof进行检查;
      • 只有在使用子类特有方法的时候才需要类型转换
      • 一般情况下,应该尽量少用类型转换和instanceof运算符
  • 多态和动态绑定

    • 抽象类

      • 抽象类不能被实例化
    • 多态:

      • 一个引用类型的变量既可以引用当前类型的对象,也可以用子类型的对象;
    • 动态绑定

      • 理解方法的调用
  • 覆盖

    • 方法名字和参数列表称为方法的签名;
    • 允许子类将覆盖方法的返回类型定义为原返回类型的子类型。称之为“协变返回类型”
  • Object

    • 编写一个完美的equals方法

      • 设计原则,equals方法要满足五个特性:

        • 1、自反性;
        • 2、对称性;
        • 3、传递性;
        • 4、一致性;
        • 5、对于任意非空引用x,x.equals(null)方法应该返回false;
      • 设计思路:

        • 1、如果子类能够拥有自己的相等概念,则对称性要求将强制采用getClass进行检测;
        • 2、如果超类决定相等的概念,那么就可以使用instanceof进行检测,这样可以在不同子类的对象之间进行相等的比较。并应该将超类的equal方法声明为final;
      • 完美的equals方法的建议:

        • 1、显示参数命名为otherObject,稍后需要将它转换成另一个叫other的变量;

        • 2、检测this域otherObject是否引用同一个对象:if (this == otherObject) return true;

          • 这个比较只是一个优化;
        • 3、检测otherObject 是否为null,如果为null,返回false: if (otherObjct == null) return false;

          • 这个检测很有必要
        • 4、比较 this与otherObject 是否属于同一个类,如果equals的语义在每个子类中有所改变,就是用getClass检!= otherObject.getClass()) return false;

4、如果所有的子类都有统一的语义,就使用instanceof检测:
if (!(instanceof instanceof ClassName)) return false;

			- Java为每个类型管理了一个Class对象。因此,可以利用 == 运算符实现两个类对象比较的操作。

		- 5、将otherObject转化为相应的类型变量:

ClassName other = (ClassName) otherName;
- 6、现在开始对所有需要比较的域进行比较了。使用==比较基本类型域,使用equals比较对象域。所有的域都匹配返回true,否则返回false;
- 7、如果子类中重新定义equals,就要在其中包含调用super.equals(other)

	- 如果重新定义equals方法,就必须重新定义hashCode方法

- toString方法

	- 只要对象与一个字符串通过操作符“+”连接起来,Java编译器就会自动调用toString方法
	- 在调用x.toString() 的地方可以用""+x替代
	- println 方法就会直接调用x.toString() 并打印输出得到的字符串
	- 强烈建议为自定义的每一个类增加toString方法
  • 泛型数组列表ArrayList

    • ensureCapacity 方法

      • 这个方法为数组列表分配一个初始容器,这样向数组列表中添加元素时,添加元素数量不大于初始化容器大小时,数组列表不用重新分配空间
    • trimToSize 方法

      • 这个方法将存储区域的大小调整为当前元素数量所需要的存储空间数目。垃圾回收器将回收多余的存储空间。

1.4 对象包装器和自动装箱

  • 对象包装器是不可变的
  • 装箱和拆箱是编译器认可的,而不是虚拟机

1.5 枚举类

  • 在比较两个枚举类型的值时,永远不需要调用equals,而直接使用“==”就可以了

  • 所有的枚举类型都是Enum类的子类

  • 最有用的方法

    • toString() 这个方法能够返回枚举常量名

      • Size.SMALL.toString() 将返回字符串“SMALL”
    • valueOf() 这个方法是toString的逆方法

      • Size s = Enum.valueOf(Size.class, “SMALL”);
        将s 的值设置为 Size.SMALL
    • values() 这个方法返回一个包含全部枚举值的数组

    • ordinal() 这个方法返回enum声明中枚举常量的位置,位置从0开始计数。

二、Java的高级特性

2.1 反射

  • 能够分析类能力的的程序称为反射

    • 在运行时分析类的能力
    • 在运行时查看对象
  • 2.1.1 Class类

    • 一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如:int不是类,但int.class 是一个class类型的对象

    • Java为每个类型管理了一个Class对象。因此,可以利用 == 运算符实现两个类对象比较的操作。

      • if(e.getClass() == Employee.class)
    • 创建一个类的实例

      • e.getClass().newInstance();
      • String s = “java.util.Random”;
        Object n = Class.forName(s).newInstance();
    • 利用反射分析类的能力

      • Class类中的getFields、getMethods、getConstructors 方法将分别返回类提供的public域、方法和构造器数组
      • Class类中的getDeclareFields、getDeclareMethods、getDeclareConstructors 方法将返回类中声明的全部域、方法和构造器
    • 实战:构建一个通用的toString 方法

2.2 接口

  • 基础概念:

    • 接口的所有方法自动地属于public
    • 接口中不能包含实例域或静态方法,但却可以包含常量。接口中的域将被自动设为public static final;
    • 接口中的方法标记为public,接口中的域将被自动设为public static final。
      Java语言规范建议不要书写这些多余的关键字。
    • 每个类只能拥有一个超类,但却可以实现多个接口;
    • 使用instanceof 检查一个对象是否属于某个特定类,也可以使用使用instanceof 检查一个对象是否实现了某个特定的接口
    • 使用逗号将实现(implement) 的各个接口分隔开;
  • 抽象类和接口

    • 抽象类表示通用属性,有一个问题;每个类只能扩展于一个类;
    • 接口可以提供多重继承的大多数好处,同时还能避免继承的复杂性和低效性。
  • 新认识:

    • 静态方法

      public interface Path{
      public static Path get(String first, String …more){
      return FileSystem.getDefault().getPath(first,more);
      }
      }

      • 在Java8中,允许在接口中增加静态方法。
      • 通常是将静态方法放到伴随类中。在标准库中,可以看到成对出现的接口和实用工具类,如:
        Collection/Collections
      • 以后在实现自己的接口时,不再需要为实用工具方法另外提供一个伴随类。
    • 默认方法

      public interface Comparable {
      default int compareTo(T other){return 0;}
      }

      • 可以为接口方法提供一个默认实现。必须使用default修饰符标记这样一个方法。

      • 默认方法可以调用任何其他方法

      • 默认方法的一个重要用途是“接口演化”

        • 为旧的接口类添加一个新的默认方法,这样可以兼容旧的代码;
      • 解决默认方法的冲突:

        • 1)超类优先;
          如果超类提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略;
        • 子主题 3
        • 2)接口冲突;
          如果一个超接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型(不论是否为默认方法)相同的方法,必须覆盖这个方法来解决冲突;
  • 标记接口:

    • 标记接口唯一的作用就是允许在类型检查中使用 instanceof
    • 建议自己的程序中不要使用标记接口
  • 函数式接口:只有一个抽象方法的接口

    • 常用的函数式接口
    • 基本的函数式接口

2.3 lambda表示式、方法引用、构造器引用

  • 概要:

    • lambda表达式是一个可传递的代码块,可以在以后执行一次或多次。

    • 函数式接口:只有一个抽象方法的接口

    • 在java中,lambda表达式所能做的也只是能转换为函数式接口。

    • 想要用lambda表达式做某些处理,还是要谨记表达式的用途,为它建立一个特定的函数式接口。

    • ArrayList类有一个removeIf方法,它的参数就是一个Predicate。这个接口专门用来传递lambda表达式。

      • // 删除数组列表中为null的值
        list.removeIf(e->e==null);
  • lambda 表达式的形式及组成:

    • lambda 表达式形式:参数,箭头(->)以及一个表达式

    • lambda有三部分构成:

      • 1)一个代码块;
      • 2)参数;
      • 3)自由变量的值,这里指非参数而且不在代码中定义的变量;
    • 代码块以及自由变量有一个术语,叫:闭包

      • lambda就是Java的闭包
    • lambda表达式可以捕获外围作用域中变量的值。但这里有一条规则:lambda表达式中捕获的变量必须实际上是最终变量。实际变量是指,这个变量初始化之后就不会再为它赋新值。

      • lambda表达式中引用的变量值,既不能在lambda表达式中改变,也不应该在外部改变。
    • lambda中不能有同名的局部变量;

    • lambda 表达式中使用this关键字时,是指创建这个lambda表达式的方法的this参数。

      • 例如:
        public class Application(){
        public void init(){
        ActionListener listener = event -> {
        System.out.println(this.toString());
        }
        }
        }

这里的this指的是ActionListener

  • lambda 表达式补充:

    • lamdba表示式的返回类型总是由上下文推导得出;
    • 需要函数式接口的时候,可以提供一个lambda表达式代替;
    • 最好把lambda表示式看做函数,而不是一个对象。lambda表达式可以转换为接口
    • 想要用lambda表达式做某些处理,还是要谨记表达式的用途,为它建立一个特定的函数式接口。
    • lambda表达式的重点是延迟执行
  • 方法引用

    有些时候已经有现成的方法可以完成你想要传递到其他代码的某个动作。

    • 方法引用,主要有三种情况:

      • object::instanceMethod

        • 如:
          System.out::println
          等价于
          x -> System.out.println(x)
      • Class::staticMethod

        • 如:
          Math::pow
          等价于
          (x,y) -> Math.pow(x,y)
      • Class::instanceMethod

        • 第一个方法会成为方法的目标
        • 如:
          String::compareToIgnoreCase
          等价于
          (x,y) -> x.compareToIgnoreCase(y)
    • 方法引用中可以使用this和super

      • 如:
        this::equals
        等价于
        x->this.equals(x)
      • super::greet
  • 构造器引用

    • 例如:Person::new 是Person构造器的一个引用
    • int[]::new 等价于 x->new int[x]

2.4 内部类

  • 为什么使用内部类:

    • 内部类方法可以访问该类定义所有的作用域中的数据,包括私有的数据;
    • 内部类可以对同一个包中的其他类隐藏起来
    • 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷
  • 内部类既可以访问自身的数据域,也可以访问创建它的外围类对象的数据域。

  • 只有内部类可以是私有类,而常规类只可以具有包可见性,或公有可见性。

  • 内部类中所有的静态方法域都必须是final

  • 内部类不能有static方法

  • 只有内部类可以声明为static

    • 在内部类不需要访问外围类对象的时候,应该使用静态内部类。
  • 内部类的种类

    • 局部内部类

      • 如果一个内部类只在被一个方法访问,就可以将这个内部类定义到方法中。
      • 局部类有一个优点:它们不仅能够访问包含它们的外部类,还可以访问局部变量;在JavaSE8 之前,局部变量声明为final;
    • 匿名内部类

      • 如果定义在方法中的内部类只创建一个对象,就可以使用匿名内部类替代。
      • 尽可能使用lambda表达式代替匿名内部类
    • 静态内部类

      • 有时候,使用内部类只是把一个类隐藏在另一个类的内部,并不需要内部类引用外围类对象。
        为此,可以将内部类声明为static,以便取消产生的引用。

2.5 代理

  • java的JDK里面提供了动态代理的方案

2.6 Java的异常

  • 异常的层次结构:

    • 所有异常都是由Throwable继承而来,
      而下一层立即分为两类:Error和Exception

    • Exception层又分解为两支:一支派生于RuntimeException,另一支包含其他异常

      • 由程序错误导致的异常属于RuntimeException

        • 如果RuntimeException出现,一定是你的问题
      • 而程序本身没问题,但由于像I/O错误这类问题导致的异常属于其他异常

  • 受查异常和非受查异常

    • 派生于Error类或RuntimeException类的所有异常称为非受查异常;
    • 所有其他异常称为受查异常
  • 策略:一个方法必须声明所有可能抛出的受查异常,而非受查异常要么不可控(Error),要么就应该避免发生。

  • 合并catch语句

    • 形式: catch(XXXException | XXXException e)

      • …
        catch (IOException|InterruptedException|ClassNotFoundException e) {
        e.printStackTrace();
        throw new RuntimeException(e);
        }
    • 只有当捕获的异常类型彼此之间不存在子类关系时才需要这个特性。

    • 捕获多个异常时,异常变量隐含为final变量,不能再子句体中为e赋不同的值。

  • 再次抛出异常,可以将原始异常设置为新异常的原因

    • 例如:
      Throwable se = new ServletException(“database error”);
      se.initCase(e);
      throw se;
    • 重新得到原始异常:Throwable e = se.getCase();
  • 强烈建议将try/catch和try/finally语句块解耦,这样可以提高代码的清晰度。

    • try{
      try{
      code that might throw exceptions
      }finally{
      in.close();
      }
      }catch(IOException e){
      show error message
      }
  • 带资源的try语句

    • 最简单的形式如:
      try (Resource res = …)
      {
      work with res
      }
    • 还可以指定多个资源:
      try (Scanner in = new Scanner(new FileInputStream("/user/words"),“UTF-8”);
      PrintWriter out = new PrintWriter(“out.txt”)){

}

	- 无论这个块如何退出,in和out都会关闭

2.7 泛型程序设计

  • 2.7.1 泛型类

    • public class Pair
  • 2.7.2 泛型方法

    • 例如:
      public static getMiddle<T… a>
    • 类型变量放在修饰符后面,返回类型的前面;
  • 2.7.2 类型变量的限定

    • 例如:
      public static T min(T[] a)…

      • 将T限定为实现了Comparable接口的类
    • 一个类型变量使用通配符可以有多个限定:
      T extends Comparable & Serializable

    • 为了提高效率,应该将标签(tagging)接口(即没有方法的接口)放在边界列表的末尾

  • 2.7.3 类型擦除

    • 虚拟机没有泛型类型对象。
    • 无论何时定义一个泛型类型,都自动提供了一个响应的原始类型。原始类型的名字就是删去类型参数后的泛型类型名。擦除类型变量,并替换为限定类型(无限定的变量用Object)
    • 为了提高效率,应该将标签(tagging)接口(即没有方法的接口)放在边界列表的末尾
  • 2.7.4 通配符类型

    • 例如:
      Pain<? extends Employee>

      • 表示任何泛型Pain类型
    • 通配符限定与类型限定十分类似

    • 但,通配符限定有一个附加能力,可以指定一个超类型限定,如:? super Manager ,这个通配符限制为Manager的所有超类型

  • 2.7.5 无限定通配符

    • class Pair<?>{
      ? getFirst()
      void setFirst(?)
      }

      • getFirst() 的返回值只赋给一个Object。setFirst方法不能被调用,甚至不能用Object调用。可以调用 setFirst(null)
    • 用来测试一个pair是否包含一个null引用

    • 非法的代码:? t = p.getFirst();// Error

2.6 应用首选项的存储

三、图形程序设计

3.1 Swing

  • 解释:“被绘制的”用户界面类。

3.2 AWT

  • 解释:像事件处理这样的窗口工具箱的底层机制。

四、部署Java应用程序

4.1 Jar文件

  • 4.1.1 创建Jar文件;

  • 4.1.2 清单文件;

  • 4.1.3 可执行Jar文件;

    • java -jar jar文件

4.2 应用首选项的存储

  • 4.2.1 属性映射

    • Properties
  • 4.2.2 首选项API

五、集合

集合框架的接口

  • Iterable

    接口

    • Collection

      Collection 是接口。
      Collection实现Iterable的接口,这样就能够使用for each 语法了

      • List
      • Set
      • Queue
  • Map

    • SortMap

      • NavigableMap
  • Iterator

    • ListIterator

集合框架中的类

  • AbstractCollection

    • AbstractList

      • AbstractSequentialList

        • LinkedList
      • ArrayList

        数组和数组列表都有一个重大的缺陷。这就是从数组的中间位置删除一个元素要付出很大的代价。在数组中间的位置上插入一个元素也是如此。

        链表(Linked list) 解决了这个问题。

    • AbstractSet

      • HashSet

        • LinkedHashSet
      • EnumSet

      • TreeSet

    • AbstractQueue

      • PriorityQueue
      • ArrayQueue
  • AbstractMap

    • HashMap

      • LinkedHashMap
    • TreeMap

    • EnumMap

    • WeakHashMap

    • IdentityHashMap

队列

  • 双端队列

  • 优先级队列

    • 使用优先级队列的典型示例是任务调度

链表

  • 在Java程序设计语言中,所有链表实际上都是双向连接的。
  • LinkedList对象根本不做任何缓存位置信息的操作。每次查找一个元素都要从列表的头部重新开始搜索。
  • 使用链表的唯一理由是尽可能减少在列表中间插入或删除元素所付出的代价。

数组列表

散列集

  • 散列表可以快速查找所需要的对象。

  • 原理:在Java中,散列表用链表数组实现。每个列表称为桶。要想查到表中对象的位置,就要先计算它的散列码,然后与桶的总数取余,所得的结果就是保存这个元素的桶的索引。

    • 散列码:hashCode
    • Java8中,桶满时会从链表变为平衡二叉树。
    • 初始化桶数
    • 散列因子
  • HashSet类,实现了基于散列表的值。

树集

  • TreeSet

    • 树集是一个有序集合
    • 排序是用树结构完成的

映射

  • 用迭代处理映射的键和值

    • scores.forEach((k,v) -> System.out.println(“key=”+k + “,value” + v));
  • HashMap和TreeMap

    两个通用的实现。

    • HashMap,对键进行散列
    • TreeMap,用键的整体顺序对元素进行排序,并将其组织成搜索树。
  • 要迭代处理映射的键和值,最容易的方法是使用forEach方法。可以提供一个接收键和值的lamdba表达式。

    • scores.forEach((k,v)->System.out.println(“key=”+k+",value="+v));
  • LinkedHashMap

    • 链接散列映射将用访问顺序,而不是插入顺序,对映射条目进行迭代。

      • 每次调用get或put,受到影响的条目将从当前位置删除,并放到条目链表的尾部(只有条目在链表中的位置会受影响,而散列表中的桶不会受影响。一个条目总位于与键散列码对应的桶中)。
  • WeekHashMap

    • 这个数据结构将与垃圾回收期协同工作,用于回收不再有任何途径引用的键值
  • IdentityHashMap

    • 键的散列值不使用hashCode函数计算的,而是用System.identityHashCode方法计算。而且对两个对象进行比较时,IdentityHashMap类使用==,而不使用equals。

视图与包装器

  • 映射类keySet() 返回一个实现了Set接口的类对象,这个类的方法对原映射进行操作。这种结合称为视图。

  • Arrays类的静态方法asList将返回一个包装了普通Java数组的List包装器。
    Card[] cardDeck = new Card[52];
    List cardList = Arrays.asList(cardDeck);
    返回的对象不是ArrayList。它是一个视图对象。

  • 同步视图

    • Collections.synchronizedMap方法可以将任何一个映射表转换成具有同步访问方法的Map
  • 受查视图

    • List safeStrings = Collections.checkedList(strings, String.class);
      ArrayList rawList = safeStrings;
      rawList.add(new Date()); // checked list throws a ClassCastException

Properties

  • 一个非常特殊的映射结构

栈 Stack

位集 BitSet

  • 由于位集将位包装在字节里。所以,使用位集要比使用Boolean对象的ArrayList更加高效。
  • 案例:查找所有的素数

六、并发

线程

  • 多进程和多线程的区别

    • 本质区别在于每个进程拥有自己的一整套变量,而线程则共享数据
  • 开启一个线程

    • 方案一:实现Runnable接口

      • lambda方式

        • Runnable r = ()->{System.out.println(“I have a dream.”);};
          Thread t = new Thread®;
          t.start();
      • 内部类方式

        • Thread t = new Thread(new Runnable(){
          @Override
          public void run() {
          System.out.println(“This is inner class”);
          }
          });
          t.start();
    • 方案二:构建一个Thread类的子类

      • 内部类方式

        • new Thread(){
          @Override
          public void run() {
          System.out.println(“I love you.”);
          }
          }.start();
      • 继承的方案

        • class MyThread extends Thread{
          @Override
          public void run() {
          System.out.println(“This extend Thread”);
          }
          }
        • Thread thread = new MyThread();
          thread.start();

中断线程

  • 每个线程都应该不时地检查这个标志,以判断线程是否被中断

  • 发送中断请求 interrupt()

    • interrupt() 方法用于请求终止线程。当对一个线程调用interrupt方法时,线程的中断状态将被置位
  • 异常

    • 在一个被阻塞的线程(调用sleep或wait)上调用interrupt方法时,阻塞调用将会被Interrupted Exception异常中断。
    • 如果中断状态被置位时调用sleep方法,它不会休眠。相反,它将清除这一状态(!)并抛出InterruptedException
  • 检查当前线程,并将中断状态重置为false

    • static boolean interrupted()
  • boolean isInterrupted()

    • 检查当前线程是否被终止

线程的状态

  • New 新创建

    new Thread®

    • Runnable 可运行

      一旦调用start方法,线程处于runnable状态

      • 被阻塞线程和等待线程

        实际上被阻塞状态与等待状态时有很大不同的

        • Blocked 被阻塞

          当一个线程试图获取一个内部的对象锁,而该锁被其他线程持有,则该线程进入阻塞状态。

          当所有其他线程释放该锁,并且线程调度器允许本线程持有它的时候,该线程将变为非阻塞状态。

        • Waiting 等待

          在调用Object.wait 方法或Thread.join 方法,或者等待java.util.concurrent 库中的Lock或Condition时,就会出现这种情况。

        • Timed waiting 计时等待

          带有超时参数的方法:
          Thread.sleep、Object.wait、Thread.join、Lock.tryLock以及Condition.await的计时版

      • Terminated 被终止

        原因一: run方法正常退出而自然死亡;
        原因二: 因为一个没有捕获的异常终止了run方法而意外死亡

线程的属性

  • 线程的优先级

    • 在Java程序设计语言中,每一个线程有一个优先级
    • 默认情况下,一个线程集成它父线程的优先级
    • 可用setPriority方法提高或降低任何一个线程的优先级
    • 每当线程调度器有机会选择新线程时,它首先选择具有较高优先级的线程。
    • 线程优先级是高度依赖于系统的。不要将程序构建为功能的正确性依赖于优先级。
    • static void yield() 导致当前执行线程处于让步状态
  • 守护线程

    • 守护线程的唯一用途是为其他线程提供服务。

      • 例如:计时线程,它定时发送“计时嘀嗒”信号给其他线程或清空过时的高速缓存项的线程。
    • 当只剩下守护线程时,虚拟机就退出了,由于如果只剩下守护线程,就没必要继续运行程序了。

    • 守护线程应该永远不去访问固有资源,如文件、数据库,因为它会在任何时候甚至在一个操作的中间发生中断。

    • setDaemon(boolean isDaemon),标记为守护线程,该方法必须在线程启动之前调用

  • 未捕获异常处理器

    • 当线程发生异常终止的时候,异常会被传递到一个用于未捕获异常的处理器。

    • 处理器必须实现一个Thread.UncaughtExceptionHandler接口的类

      • 这个接口只有一个方法:void uncaughtException(Thread t, Throwable e)
    • 安装线程处理器

      • 可以使用setUncaughtExceptionHandler()方法为任何线程安装一个处理器

        • Thread t = new Thread(()->{int i=1/0;});
          t.setUncaughtExceptionHandler((tt, e)->{System.out.println(“There has exception.”);});
          t.start();
      • 也可以用Thread类的静态方法setDefaultUncaughtExceptionHandler为所有线程安装一个默认的处理器

同步

  • 背景:在多线程应用中,两个或两个以上的线程需要共享对同一数据的存取。

  • 进行同步的两种机制

    • 方案一:synchronized关键字,同步方法

      • synchronized关键字自动提供一个锁以及相关的“条件”
    • 方案二: 使用锁

    • 方案三: 同步代码块

  • 锁对象

    • 方案二:ReentrantLock类, jdk1.5提供

      • ReentrantLock()

      • ReetrantLock(boolean fair)

        • 创建一个公平策略的锁。一个公平锁偏爱等待时间最长的线程。但这一公平的保证将大大降低性能。所以,默认情况下,锁没有被强制为公平的。
      • myLock.lock();// a ReentrantLock object
        try{
        critical section
        }finally{
        // make sure that lock is unlocked even if an exception is thrown
        myLock.unlock();
        }

    • 概述

      • 锁用于保护代码片段,任何时刻只能有一个线程执行被保护的代码
      • 锁可以用户一个或多个相关的条件对象
      • 使用锁就不能使用带资源的try语句
  • 条件对象

    • Condition

      • Condition condition = bankLock.newCondition();
    • 每个条件对象管理哪些已经进入被保护的代码段但还不能运行的线程。

    • bankLock.lock();
      try{
      while(condition){
      condition.await();
      }
      critical section
      condition.signalAll();
      }finally{
      bankLock.unlock();
      }

  • synchronized 方法

    • 从jdk1.0 版本,Java中的每一个对象都有一个内部锁。如果一个方法用synchronized关键字声明,那么对象的锁将保护整个方法。 也就是说,要调用方法,线程必须获得内部锁的对象锁。

    • 案例:

      • public synchronized void transfer(int from, int to, double amount) throws InterruptedException{
        // 加条件锁
        while (accounts[from] < amount) {
        wait();
        }
        System.out.println(Thread.currentThread());
        accounts[from] -= amount;
        System.out.printf(" %10.2f from %d to %d", amount, from, to);
        accounts[to] += amount;
        System.out.printf(" Total Balance: %10.2f%n", getTotalBalance());
        notifyAll();
        }
  • synchronized 代码块

    • private Object lock = new Object();
      public void method(){
      synchronized(lock){
      critical section
      }
      }

      • 这里lock对象被创建仅仅是用来使用每个Java对象持有的锁。
  • volatile 域

    • 在一个域上声明volatile,那么编译器和虚拟机就知道该域是可能被另一个线程并发更新的。
  • final变量

    • final Map<String, Double> accounts = new HashMap<>();

      • 其他线程会在构造函数完成构造之后才看到这个accounts变量。
  • 原子性

    • java.util.concurrent.atomic包中有很多类使用了很高效的机器级指令(而不是使用锁)来保证其他操作的原子性。
  • 死锁

  • 线程的局部变量

    • 使用ThreadLock辅助类为各个线程提供各自的实例

    • 例如: SimpleDateFormat不是线程安全的。
      public static final SimpleDateFormat dataFormat = new SimpleDateFormat(“yyyy-MM-dd”);
      如果两个线程都执行以下的操作:
      String dateStamp = dateFormat.format(new Date());
      dateFormat 使用的内部数据结构可能会被并发的访问破坏。

      • 可以使用同步,但开销很大;也可以在需要的时候创建一个局部的SimpleDateFormat对象,不过这也太浪费了。

      • 可以使用以下代码,为每个线程创建一个实例:

        • public static final ThreadLocal dateFormat = ThreadLocl.withInitial(()->new SimpleDateFormat(“yyyy-MM-dd”));
        • 要访问具体的格式化方法,可以调用:
          String dateStamp = dateFormat.get().format(new Date());
    • java.util.Random类是线程的。但如果多个线程需要等待一个共享的随机数生成器,这会很低效。可以使用ThreadLocal辅助类为各个线程提供一个单独的生成器。

      • 不过jdk1.7 提供了一个便利类。只需要做以下调用:
        int random= ThreadLoclRandom.current().nextInt(upperBound);

        • ThreadLoclRandom.current() 调用会返回特定于当前线程的Random类实例。
  • 锁测试与超时

    • myLock.tryLock()

      • tryLock方法视图申请一个锁,在成功获得锁后返回true,否则立刻返回false,而且线程可以立刻离开去做其他事情。
    • myLock.tryLock(100, TimeUnit.MiLLISECONDS))

    • myLock.await(100, TimeUnit.MiLLISECONDS))

  • 读/写锁

    • ReentrantReadWriteLock

    • 很多线程从一个数据结构读取数据而很少线程修改器数据的话,ReentrantReadWriteLock是十分有用的。

    • 步骤

      • // 构建对象
        priavte ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
        // 获取读锁和写锁
        private Lock readLock = rwl.readLock();
        private Lock writeLock = rwl.writeLock();

      • 对读方法加读锁

      • 对写方法加写锁

        • public void transfer(){
          writeLock.lock();
          try(){}
          finally{writeLock.unLock();}
          }
  • 弃用stop和suspend方法

    • 这两个方法有一些共同点:都试图控制一个给定线程的行为
    • stop方法天生不安全,无法知道什么时候调用stop方法是安全,什么时候导致对象破坏
    • suspend方法容易导致死锁

阻塞队列

阻塞队列就是线程安全的集合。

  • 背景

    • 对于实际编程应该尽量远离底层。
    • 对于多线程问题,可以通过使用一个或多个队列以优雅且安全的方式将其形式化。
  • java.util.concurrent

    • LinkedBlockingQueue

      • 容量是没有上边界的,但是也可以选择指定最大容量
    • LinkedBlockingDeque

      • 是一个双端版本
    • ArrayBlockingQueue

      • 在构造时需要指定容量,并且有一个可选的参数来指定是否需要公平性。通常公平性会降低性能,只有在确实非常需要时才使用它。
    • PriorityBlockingQueue

      • 一个带有优先级的队列,而不是先进先出队列。元素按照它们的优先级顺序被移出。该队列是没有容量上限,但是,如果队列是空的。取元素的操作会阻塞
    • DelayQueue

      • 实现了Delayed接口。getDelay方法返回对象的残留延迟。负值表示延迟已经结束。元素只有在延迟用完的情况下才能从DelayQueue移出。
      • 同时还必须实现compareTo方法,DelayQueue使用该方法对元素进行排序。
    • TransferQueue 接口(jdk1.7 增加)

      • LinkedTransferQueue

      • 这个接口,允许生产者线程等待,直到消费者准备就绪可以接受一个元素。

        • 如果生产者调用q.transfer(item) 这个调用会阻塞,直到另一个线程将元素删除。
  • 使用

    • 第一类

      • 将队列当做线程管理工具来使用,put和take方法
    • 第二类

      • 当试图向满的队列中添加或从空的队列中移出元素时,add、remove和element操作会抛出异常
    • 第三类

      • offer、poll、和peek方法

        • 这些方法如果不能完成任务,只是给出一个错误提示而不会抛出异常。

线程安全的集合

  • 高效的映射、集、队列

    • java.util.concurrent

      • ConcurrentHashMap
      • ConcurrentSkipListMap
      • ConcurrentSkipListSet
      • ConcurrentLinkedQueue
    • 确定这样的集合当前的大小通常需要遍历

  • 同步包装器

    • 任何集合类都可以通过同步包装器(synchronizationwrapper)变成线程安全的

      • List synchArrayList = Collections.synchronizedList(new ArrayList();
      • Map<K, V> synchHashMap = Collections.synchronizedMap(new HashMap<K, V>());
    • 如果在另一个线程可能进行修改时要对集合进行迭代,仍然需要使用“客户端”锁定

      • synchronized(synHashMap)
        {
        Iterator iter = synHashMap.keySet().iterator();
        while(iter.hasNext)…
        }

Runnable、Callable和Future

  • Runnable封装一个一部运行的任务,可以将其想象成为一个没有参数和返回值的异步方法。

  • Callable与Runnable类型,但是有返回值。Future 保存异步计算的结果

    • Callable接口是一个参数化的类型,只有一个方法call

      • public interface Callable{
        V call() throws Exception;
        }
    • 可以启动一个计算,将Future对象交给某个线程,然后忘掉它。Future对象的所有者在计算好之后就可以获得它。

  • 分析Future的方法

    • get() throws…

      • 这个get方法的调用被阻塞,直到计算完成
    • get(long timeout, TimeUnit unit) throws…

      • 这个方法调用超时时,会抛出TimeoutException异常
    • 如果在运行过程中,线程被中断,两个方法都将抛出InterruptedException。如果计算已经完成,那么get方法立刻返回

  • FutureTask 包装器

    • 可以将Callable转换成Future和Runnable

线程池

  • 使用线池的好处

    • 1、减少并发线程的数目;
    • 2、一个线程可以多次提供服务;
  • 通过执行器类Executor的静态方法来构建线程池

    • newCachedThreadPool

      • 必要时创建新线程;空闲线程会被保留60秒;
    • newFixedThreadPool

      • 创建固定数量的线程,空闲线程会一直被保留
    • newSingleThreadExecutor

      • 只有一个线程的“池”,该线程顺序执行每一个提交的任务
    • 预执行器

      • newScheduledThreadPool

        • 用于预定执行而构建的固定线程池
      • newSingleThreadScheduledExecutor

        • 用于预定执行而构建的单线程“池”
      • 为预定执行或重复执行任务而设计

  • 实现线程池的步骤

    • 第一步:调用Executor类中静态方法创建线程池

    • 第二步:调用线程池submit方法提交Runnable或Callable对象;

    • 第三步:保存好返回的Future对象

    • 第四步:当不再提交任何任务的时候,调用shutdown方法。关闭线程池

      • 调用shutdown方法,执行器关闭,不再接受新的任务。当所有任务都完成以后,线程池中的线程死亡。
      • 另一个中方法是调用shutdownNow,该池取消尚未开始的所有任务并试图中断正在运行的线程
  • 控制任务组

    • 有时,使用执行器更有实际意义的原因,控制一组相关任务

      • 可以提交很多任务,每个任务使用一种方法处理一个问题,只要其中一个任务得到答案,计算停止(调用 shutdownNow方法)
    • invokeAny

      • 提供所有对象到一个Callable对象的集合中
      • List<Callable> tasks = …;
        List<Future> results = executor.invokeAll(tasks);
        for(Future result: results) processFurthrer(result.get())
    • ExecutorCompletionService

      • 对结果按可获得的顺序保存起来
  • Fork-Join框架

    • 讲一个大任务拆分成一个个小任务,最后将结果汇总

    • 步骤

      • 步骤一:扩展一个RecursiveTask类,或扩展RecursiveAction类;

        • invokeAll方法接收到很多任务并阻塞
        • 对每个子任务应用join,并返回其合计的结果
      • 第二步:创建ForkJoinPool 对象,并调用invoke方法提交recursiveTask

        • join方法返回结果

同步器

七、书籍推荐

看以下三本书籍,更有利于理解并发

  • 《Java编程思想》

    • D瓜哥:推荐先读并发那章
  • 《Effective Java》

    • D瓜哥:还可以看看中关于并发的描述
    • 左耳朵狮子:如果C和OS基础不错,可以直接看effective java
  • 现代操作系统 或 操作系统精髓

XMind: ZEN - Trial Version

《Java 核心技术卷1 基础知识》第一章 Java程序设计概述 笔记 现在的即时编译器已经非常出色,可以与传统编译器现媲美,而且在某些情况下甚至超越了传统编译器,原因是它们有更多的可用信息。Java 是强类型的,编译器能捕获类型滥用导致的很多错误。编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码,只要有 Java 运行时系统,这些编译后的代码可以在许多处理器上运行。不同的厂商会选择不同的中央处理器(CPU),因此很重要的一点是这种语言不应与任何特定的体系结构绑定。不过,像 Gosling 在专访中谈到:“毕竟,语言只是实现目标的工具,而不是目标本身”。 阅读详情

相关推荐

Java核心技术卷Ⅰ(一)—— Java基本程序结构及数据类型

Java基础部分,主要包括java程序的简单结构,数据类型,运算符等等

假如的博客 519

Java 核心技术卷1 第一章 java程序设计概述

正像我们在第1版中已经指出的那样,Java并不只是一种语言。在此之前出现的那么多种语言也没有能够引起那么大的轰动。作为一名程序设计人员,常常希望能够有一种语言,它具有令人赏心悦目的语法和易于理解的语义(C+不是这样的)。与许多其他的优秀语言一样,Java恰恰满足了这些要求。有些语言,但是,没有提供一个大型的库。如果想要有奇特的绘图功能、网络连接功能和数据库存取功能就必须自己动手编写代码。正是因为它集多种优势于一身,所以对广大的程序设计人员有着不可抗拒的吸引力。

trigger的博客 1289

呕心搬运!Java 核心技术卷一知识点最全总结贴

呕心搬运!Java 核心技术卷一知识点最全总结贴 千呼万唤始出来,本来觉得看书容易忘记,不如记一点笔记,于是从头开始把Java核心技术卷一慢慢的抄了一遍。也许抄的过于过分,修改的地方也不多,但是我觉得还是尽可能保持原味,除非是一些有触发的东西,可以稍微添上。 整个抄书的过程,没多久就想放弃了,太费时间了,而且前面还基本都是对知识点的手打(后面换成从ocr书上复制),怎么说,这也算是争一口气,给自己一个坚持学习下去的目标,很开心最后完成了,虽然给自己的完成时间是一个半月,最后多用了一个月,工作上的事虽然多,但

silencefly的博客 4225

Java核心技术 读书笔记

面向对象编程OOP是现在的主流,Java是完全面向对象的。OOP由对象构成,每个对象中有对用户公开的特定功能部分,也有隐藏的实现部分。结构化编程是先考虑算法的设计,再去考虑数据的存储方式。OOP则是先考虑数据的存储方式,再考虑操作数据的算法。使用Java中预先定义的Data类来介绍类的使用方法。现在介绍如何设计复杂应用程序所需要的各种主力类。这些类没有main方法,但是有自己的数据域和实例方法(实例方法不是静态方法)。这些类自己不能运行,通过设计的目的是被调用。

qq_45651829的博客 1282

Java核心技术卷1+卷2第8版完整学习指南

Java语言由Sun Microsystems于1995年正式发布,是一种面向对象、跨平台、多线程支持的高级编程语言。其设计初衷是为了实现“一次编写,到处运行”(Write Once, Run Anywhere)的目标,这得益于Java虚拟机(JVM)机制的支撑。随着技术演进,Java不断迭代升级,从最初的Java 1.0到如今的Java 11,每个版本都带来了语法增强、性能优化和新特性支持。

weixin_28988985的博客 769

【上海大学计算机组成原理实验报告】七、程序转移机制

学习实现程序转移的硬件机制//掌握堆栈寄存器的使用//手动方式实现子程序调用转移过程//手动方式实现子程序返回转移过程//编程实现`OUT`寄存器交替显示`11`和`55`//若要求`11`和`55`各显示`50`次后停机,应该如何修改程序?//根据实验指导书的相关内容,实验箱系统的程序转移硬件机制在于,当`LDPC`有效时,如果此时`DUBS`上的值就是转移的目标地址,则此目标地址被打入`PC`,从而实现程序的转移;若`LDPC`为`0`是附带条件的,就形成“条件转移”。

HackerKevon的博客 2474

《java核心技术_卷二:高级特性》(一)1-7章 思维导图

《java核心技术_卷二:高级特性》(一)1-7章 思维导图 资源地址:dssds

makunyuan123的专栏 1165

SICK LMS111激光雷达数据解析实战:从原始帧到三维点云的完整流程

本文详细解析了SICK LMS111激光雷达从原始数据帧到三维点云的完整处理流程,包括数据帧结构解析、坐标转换、点云可视化及性能优化技巧。通过实战代码示例,展示了如何高效处理激光雷达数据,并应用于动态物体检测、地面分割等工业场景,为AGV和服务机器人开发者提供实用指南。

garlic的博客 769

《java核心技术_卷一:基础知识》(一)1-3章 思维导图

《java核心技术_卷一:基础知识》(一)1-3章   思维导图

makunyuan123的专栏 1569

Cherry Studio部署MCP服务报错全记录:从零解决‘Connection closed‘问题

本文详细记录了在Cherry Studio中部署MCP服务时遇到‘Connection closed’报错的完整排查与解决过程。文章从环境依赖(UV、Bun)的安装验证、绝对路径配置、网络镜像源设置,到服务端手动调试与Cherry Studio配置检查,提供了一套系统性的解决方案,帮助开发者彻底解决此类连接问题。

g9h0i1的博客 765

详细对比模型训练和模型精调

当我们进行模型精调(Fine-Tuning)和模型训练时,我们需要考虑到不同的步骤和目标。

pumpkin84514的博客 1853

【总结】Java核心技术36讲知识点大纲

前段时间在极客时间上购买了杨晓峰老师的《Java核心技术36讲》,趁着这段时间有空,对相关知识点做了一个整体的目录,也对自己所掌握的Java基础进行了一个复习和梳理,若想深入学习,可以购买相关专栏,也可以对着该知识点查阅相关资料,源码等自学。—-kayfen 文末附专栏链接 Java核心技术36讲知识点总结 1 Java平台的理解 Java的特性,解释运行和编译运行 2 E...

Kaybee - 练级之路 1万+

AD20丝印层导入图片logo保姆级教程(附黑白预览避坑技巧)

本文提供了一份详尽的AD20丝印层导入图片Logo的实战指南。核心在于将图片预处理为高质量的单色BMP位图,并独家分享了利用Windows画图工具进行“黑白预览”的关键技巧,以提前规避转换失真。教程涵盖了从脚本获取、图片处理、参数设置到生产规范的完整流程,帮助硬件工程师高效、准确地在PCB的Top Overlay层添加个性化标识。

weixin_29194255的博客 386

《Java核心技术 卷1 基础知识 原书第10版》

/*免责声明:全部内容都属于是段友分享,我只是属于整理。**/ /*写在前边,个人觉得****弄一个积分下载,就是在自掘坟墓。表面上看起来是可以为个人赚积分,实际砍掉分享交流的一个途径。对我就是没有积分,我就是这么理直气壮。所以每次需要东西的时候,网上一艘,全都是积分下载,虽然有的只是1分,但是不好意思我真的没有,我觉得不想分享别分享啊。到了这里,我把我有的就分享出来,我在博客上专门...

Angus 2万+

VTK四视图联动避坑指南:解决vtkImagePlaneWidget窗宽窗位同步与切片序号更新的那些坑

本文详细解析了VTK四视图联动开发中的关键技术点与常见问题,包括切片位置同步、窗宽窗位同步的实现原理及回调机制设计。针对开发中遇到的回调事件不触发、渲染性能低下等问题,提供了实用的解决方案和优化技巧,帮助开发者高效构建医学影像和科学可视化应用。

weixin_42638178的博客 392

使用MATLAB结合EasySpin进行ESR模拟的详细步骤及示例代码

安装EasySpin:确保你已经安装了EasySpin工具箱,它可以帮助你进行ESR模拟。你可以从EasySpin的官方网站(https://easyspin.org/)下载并安装。准备实验数据:将实验得到的EPR数据整理成合适的格式,一般包含磁场(Magnetic Field)和信号强度(Intensity)两列。进行模拟:使用EasySpin的函数对单线态氧自由基和超氧自由基进行模拟。调整参数:通过调整模拟参数,使模拟得到的峰型和峰位置与实验数据尽可能匹配。导出数据。

AI的内部世界的博客 2005

【免费下载】 Java核心技术第12版(卷1+卷2)合集

Java核心技术第12版(卷1+卷2)合集 【下载地址】Java核心技术第12版卷1卷2合集 本仓库提供了《Java核心技术第12版(卷1+卷2)》的资源文件下载。该书是Java编程领域的经典教材,涵盖了Java语言的核心概念和高级特性,适合Java初学者和有经验的开发者阅读。 ...

gitblog_09750的博客 1万+

【AI智能体】飞书 AI 智能客服机器人搭建与使用实战操作详解

飞书 AI 智能客服机器人搭建与使用实战操作详解

congge 6057

《Java核心技术·卷 I》知识点精粹总结

这本书适合有一定编程基础(不一定是Java)的学习者,也适合想要巩固和深化Java基础的开发者。它覆盖了Java SE(标准版)的核心特性,是学习后续高级框架(如Spring)的坚实地基。对于读过的人,它可以作为一个优秀的知识点回顾清单,帮你查漏补缺。我的总结将按照书中知识点的递进顺序,从基础到进阶,为你清晰地梳理出整个知识体系。这是本书的核心和精华所在,深入讲解了Java的OOP思想。这本书被誉为Java领域的“圣经”之一,它的特点是。这部分是Java的入门,涵盖了最基本的语法和概念。

千里之外的专栏 1259

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【读】Java核心技术卷1

阅读原文:【读】Java核心技术卷1 看到这本书时,我的内心是崩溃的,卷1就700多页,但是这本书是很多前辈所推荐的,想必其中必有精华所在,硬着头皮上吧。 如何阅读本书 拿到书的第一眼肯定去看目录,大概了解一下,各个章节所讲内容。 为表对作者的尊重,快读扫读了,译者序、前言和致谢。 通过目录了解到,第1,2章所讲概述和环境搭建,对于我来说没有价值,选择忽略。 第10,11,12,13章所讲Ja...

王不二 986

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

JAVA核心技术卷1 corejava.zip 下载地址

JAVA核心技术卷1 第11版: 官方下载地址:http://horstmann.com/corejava/corejava.zip 百度云链接:https://pan.baidu.com/s/13yOv0iyBWonv21Oytvrnhw提取码: fqwe

hello world 7876

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

《Java核心技术·卷 II》知识点精粹总结

《Java核心技术·卷 II》是Java高级开发的实战指南,重点讲解文件I/O、网络编程、数据库连接等核心API。文件I/O部分涵盖传统的流式操作和高效的NIO技术;网络编程介绍Socket通信和HTTP客户端;数据库章节详解JDBC的使用规范和安全实践。此外还涉及XML处理、国际化、安全加密等企业级开发必备技能。通过系统学习这些"官方武器库",开发者能构建功能强大、安全可靠的应用系统,全面掌握Java平台的高级特性。

千里之外的专栏 635

对《Java核心技术卷一》读者的一些建议

思想不会变,所以《Java编程思想》还停留在第 4 版(2007 年);而技术是要更新迭代的,所以《Java核心技术卷一》来到了第十版(2016 年)。 我们来看一下《Java核心技术卷一》第十版的大纲。 前九章:包括 “Java 程序设计概述”、“Java 程序设计环境”、“Java 的基本程序设计结构”、“对象与类”、“继承”、“接口”、“lambda 表达式与内部类”、“异常”、“断言和日...

沉默王二 1万+

Java核心技术(卷1) 10th 总结(兼与Java编程思想等对比)

总结  前一段时间把《核心卷》的卷一看完了,后来又看完了《图解TCP/IP》,月初考了一个证券从业证书,还有实验室的事情,实在是很忙。眼瞅着到月底了,还是抽出时间做个总结。关于Java基础的书,前后看的有四本,包括《Thinking in Java》,《Head First Java》,《Java核心卷》卷一和《Java开发实战经典》(国人写的)。个人感觉,好的书真的是各有各的特点,不好的书只是内容

ananhao的博客 1万+
上一篇: Java正则表达式的\P{L}
下一篇: 基于二分查询树(BinarySearchTrees)实现的键值对表(symbole-table)
鲲鹏飞九万里
博客等级 码龄10年 177粉丝 350原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值