转载

java笔记-one(简记)

  • 自动装箱:自动将基本的数据类型封装为对象类型
  • ... 是代码的一部分,表示这个方法可以接收任意的数量的对象。
  • 允许将一个数组传递给可变参数方法的最后一个参数 可以将已经存在且最后一个参数是数组的方法重新定义为可变参数的方法,而不会破坏任何已经存在的代码

反射:能够分析类能力的程序称为反射(reflective)

反射机制可以用来:

  • 在运行时分析类的能力。
  • 在运行时查看对象,例如,编写一个toString方法供所有类使用。
  • 实现通用的数组操作代码。
  • 利用Method对象,这个对象很像C++中的函数指针
  • Class类(对象将表示一个特定类的属性): 保存 运行时的类型标识(一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类。例如,int不是类,但int.class是一个Class类型的对象) 检查异常:就是编译器要求你必须处置的异常 非检查异常:编译器不要求强制处置的异常

接口:描述类有什么功能,而不是给出每个类的具体功能的实现

接口中的所有方法自动属于public

接口绝不能含有实例域,在JAVASE8之前,也不能在接口中实现方法

使用关键字“interface”声明一个接口;使用关键字“implements”声明一个类实现一个接口。

与类的权限的限制相同,接口的也能被设置为public,static,final,也就是说在接口声明的变量都会被隐式的提升为“公有的静态常量”

接口不可以实例化,但是可以引用实现了接口的类的对象;

接口中声明的方法都是抽象的,并且被自动的设置为public。

接口自身不能够被构造实例化,但可以通过实现该接口的类的方法进行实现。

实现接口的类若不是抽象类,那么该类必须实现接口的所有方法。

接口与接口之间也可以实现继承关系,子接口除拥有父接口的所有方法声明外,还可以定义新的方法声明。

如同使用instanceof检查一个对象是否属于某个特定类一样,也可以使用instance检查一个对象是否实现了某个特定的接口

与建立类的继承关系一样,接口也可以被扩展,这里允许多条从具有较高通用性的接口到较高专用性的接口的链

尽管每个类只能拥有一个超类,但却可以实现多个接口。

方法二义性的解决:

  • 1.超类优先。(超类与实现的接口都有相同的方法,接口的方法被忽略)
  • 2.接口冲突。(须覆盖掉,或在实现接口处选择二者其一)

回调:指出某个特定事件发生时应该采取的动作的模式。

简单的理解(浅拷贝):如果想要为对象创造一个副本,且它们的状态互不影响,那么应使用clone(克隆,一个新的对象,但是数据是克隆而来的)而不是引用

浅拷贝:不会克隆对象引用的其他对象,克隆对象后可能还会存在与原对象共享信息的情况。(如果共享的对象是不可变的,或者是属于一个不可变的类,对象的生命周期中,子对象一直包含不变的常量,那么这种共享是安全的)

一般的子对象是可变的,所以应该应设置一个深拷贝的clone以便于完全的复制出独立的副本

深拷贝:应对实例域的可变类进行另外的克隆。

lambda表达式:是一个可传递的代码块,可以在以后执行一次或者多次。(parameters)-> expression(表现形式:参数,→,一个表达式,如果代码要完成的计算无法放在一个表达式中,则可以像写方法一样,把这些代码放在{})

即使lambda表达式没有参数,依然需要提供空括号,就像无参数一样。

如果可以推导出一个lambda表达式的类型,则可以忽略其类型。

如果方法只有一个参数,而这个参数的类型可以推导得出,那么甚至可以省略小括号。无需指定返回类型,会依据上下文推导出来。

对于Lambda表达式中的多个参数,如果需要显示声明一个参数的类型,那么必须为所有的参数都声明类型。

注意:如果一个lambda表达式只在某些分支返回一个值,而在另外一些分支不返回值,这是不合法的。如 (int x) -> {if(x >= 0)return 1;}

函数式接口:对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式。

注意:不能把lambda表达式赋值给类型为Object的变量,Object不是一个函数接口。

lambda表达式由三部分组成:

  • 1)一个代码块
  • 2)参数
  • 3)自由变量的值,这里指的是非参数而且不在代码块中定义的变量
  • lambda表达式可以捕获作用域中变量的值(确保捕获的值是明确定义的,且只能引用值不会改变的变量(如果是在外部改变的,也是不合法的))。
  • 规则:lambda表达式中捕获的变量必须实际上是最终变量,也就是说变量初始化后不会再为它赋新值。
  • 在一个lambda表达式中使用this关键字时,是指创建这个lambda表达式的方法的this参数

使用lambda表达式的重点是延迟执行,原因如下:

1.在一个单独的线程中运行代码 2.多次运行代码 3.在算法的适当位置运行代码(排序中的比较操作) 4.发生某种情况时执行代码(点击了一个按钮,数据到达) 5.只有在必要的时候才运行代码 6.要接受这个lambda表达式,需要选择(偶尔可能需要提供)一个函数式接口

使用内部类的原因:

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

内部类的对象总有一个隐式的引用,指向了创建它的外部类对象。(它是不可见的) 外围类的引用在构造器中设置(该引用类似于c++的this指针) 外围类引用的正规语法: OuterClass.this 编写内部对象的构造器: outerObject.new InnerClass(construction parameters) 外部类之外的引用内部类:OuterClass.InnerClass 注意:内部类中声明的所有静态域都必须是final;不能有static方法

局部内部类:

不用public或private访问说明符进行声明; 作用域:声明它的这个块 优势:对外部可以完全隐藏起来,外部类中其他的代码也无法访问,可以访问局部变量(事实上是final)

匿名内部类:

语法格式: new SuperType(construction parameters) { inner class methods and data } 静态内部类没有对生成它的外围类对象的引用特权。

派生于RuntimeException的异常有以下几种情况:

  • 错误的类型转换
  • 数组访问越界
  • 访问null指针

不是派生RuntimeException的异常:

  • 试图在文件尾部后面读取数据
  • 试图打开一个不存在的文件
  • 试图根据给定的字符串查找Class对象,而这个字符串表示的类并不存在

应该抛出异常的情况:

  • 调用一个抛出受查异常的方法
  • 程序运行过程中发现错误,并且利用throw语句抛出一个受查异常
  • 程序出现错误,例如,a[-1] = 0会抛出一个ArrayIndexOutOfBoundException这样的非受查异常
  • JAVA虚拟机和运行时库出现的内部错误

不管是否有异常被捕获,finally子句中的代码都被执行; 堆栈轨迹是一个方法调用过程的列表,它包含了程序执行过程中方法调用的特定位置,如:printStackTrace(访问堆栈轨迹的文本信息描述) getStackTrace方法:得到StackTraceElement对象的一个数组,可以在你的程序中分析这个对象数组。StackTraceElement类含有能够获得文件名和当前执行的代码行号的方法,还含有获得类名和方法名的方法。

使用异常机制的技巧:

  • 异常处理不能代替简单的测试(捕获异常会花费更多的时间)且基本规则:只有异常情况下使用异常机制
  • 不要过分细化异常
  • 利用异常层次结构
  • 不要压制异常
  • 在检测错误的时候,”苛刻“要比放任更好
  • 不要羞于传递异常

断言机制: 允许在测试期间向代码插入一些检查语句,当代码发布时,插入的检测会自动移除

  • 关键字:assert 条件; or assert 条件:表达式;(会对条件进行检测,第一个会抛出AssertionError异常,第二个会将表达式传入AssertionError的构造器,且转换成一个消息字符串)
  • 注意:断言失败是致命的、不可恢复的错误;断言检查只用于开发和测试阶段(故不应该使用断言向程序的其他部分通告发生了可恢复性对的错误或者不应该作为程序向用户通告问题的手段)

记录日志:

  1. 优点:
  • 可以很容易地取消全部日志记录,或者仅仅取消个别的日志,而且打开和关闭也很容易
  • 可以很简单地禁止日志记录的输出(使得留在程序的开销很小)
  • 日志记录可以被定向到不同的处理器(用于控制台显示,用于存储在文件)
  • 日志记录器和处理器都可以对记录进行过滤(根据过滤实现器制定标准丢弃无用的记录项)
  • 日志记录可以采用不同的方式格式化
  • 应用程序可以使用多个日志记录器,它们使用类似包名的这种具有层次结构的名字
  • 在默认的情况下,日志系统的配置由配置文件控制。(如果需要的话,应用程序可以替换这个配置)

2.自己定义定义日志记录器: private static final Logger myLogger = Logger.getLogger("com.mycpmpany.myapp") (未被任何变量引用的日志记录器可能被垃圾回收,所以要使用一个静态变量存储日志记录器) 3.日志记录器级别:

  • 与包名相比,日志记录的层次性更强(父与子之间会共享一些东西)
  • SEVERE
  • WARNING
  • INFO
  • 以下级别最好用来记录那些有助于诊断但对程序员无多大意义的调试信息:
  • CONFIG
  • FINE
  • FINER
  • FINEST
  • 默认情况下只记录前三(可以自己设置: logger.setLevel(Level.FINE) ,可以使用 Level.ALL or Level.OFF 开启或者关闭所有级别的记录)
  • 如果要记录的级别设计为INFO或更低,须更改日志处理器
  • 可以通过编辑配置文件来修改日志系统的各种属性,配置文件存在于:jre/lib/logging.properties
  • 要想使用另一个配置文件,需将 java.util.logging.config.file特性设置为配置文件的存储位置且以该命令启动应用程序: java -Djava.util.logging.config.file=configFile MainClass
  • 修改默认的日志记录级别,须编辑配置文件并修改该命令行: .level = INFO 可以通过添加一下内容指定自己的日志级别: com.mycompany.myapp.level = FINE
  • 若想在控制台上看到FINE级别的消息: java.util.logging.ConsoleHandler.level=FINE
Logger logger = Logger.getLogger(LoggerName,''com.mycompany.logmessages'')

调试技巧:1)在每个类中放置一个单独的main方法。只需在main中调用所有方法,看是否能正常运行。2)日志代理是一个子类的对象,可以截获方法的调用,并进行日志记录,然后调用超类中的方法;3)利用Throwable类提供的printStackTrace方法,可以从任何一个异常对象中获得堆栈情况。(不必要通过捕获来生成堆栈轨迹,任何位置都可以插入 Thread.dumpStack() 来获取堆栈轨迹)

原文  https://juejin.im/post/5cc2ecfe51882519100565b3
正文到此结束
Loading...