java学习

java语法

  1. super关键字在子类内部使用,代表父类对象。
(1)访问父类的属性 super.属性名
(2)访问父类的方法 super.bark()
(3)子类构造方法需要调用父类的构造方法时,在子类的构造方法体里最前面的位置:super()

第三点和python他妈的就是一样的呀

  1. 当然在方法重写时我们需要注意,重写的方法签名要一致
  2. 发现了java当中一件很神奇的事情,静态的变量或者是方法是比实例低一个层级的,前者不能访问后者,后者可以访问前者,而且java当中的成员变量不同于python当中的类变量,应该是静态变量才等同于类变量,这一点要区分,那么由于java成员变量可以定义在构造函数之外,构造函数中的成员变量可以与静态变量冲突么?测试了一下,真是日了狗了,java不能在构造函数当中为实例定义自己的实例变量(貌似),所有变量都放在类定义当中去处理,这样自然没有什么覆盖的问题了

4. 接口相当于就是一个完全抽象类,其所有成员都是static final类型,final类型的变量是不支持初始化的 7. java当中重载和重写不是一个概念,重载只是同名但不同的方法 8. 这样来看spring mvc也是符合servlet接口的一种实现,这样来看就简单多了

注解

springMVC的DispatcherServlet继承自 FrameworkServlet继承自HttpServletBean 继承自HttpServlet(也就是你说的servelt) 本质上是一样的东西

  1. 执行一个包内的java程序一定要在包外部

注解

Start by making sure you are at the directory above the top level package

If the class belongs to the package com.foo.bar, you want to be in the directory above com.

In your case, you want to be in the directory above startPack.

Then you need to use the fully qualified name to run the class…

java statPack.mainClass For example…

11. class.forname一般被用来注册驱动程序 14. 关于java注解,通过反射机制为类、方法、变量等提供元信息

注解的作用

(1)格式检查:告诉编译器信息,比如被@Override标记的方法如果不是父类的某个方法,IDE会报错
(2)减少配置:运行时动态处理,得到注解信息,实现代替配置文件的功能
(3)减少重复工作:比如第三方框架xUtils,通过注解@ViewInject减少对findViewById的调用,类似的还有(JUnit、ActiveAndroid等)

关于注解的详细文章可以看 这篇

  1. bean的意思就像豆荚一样,是保存数据的实体,也就是类当中那一个个的类变量

17. java bean算是一套规则,其意义见 这里 19. 关于java远程调试的原理,看 这里 22. 领域对象(DO)一般都要实现Serializable接口,以便进行序列化 23. java bean最初是被用来做可视化组件的类,其是一套命名规则,在这样的命名规则下可以IDE(或者其他调用者)可以清晰地区分哪些是属性,哪些是事件(单纯的反射做不到么?)所以所谓的java bean其实就是具备此种命名规则的类,bean其实就是组件的意思,就像豆荚里的豆子,一个豆荚里面有很多可用的豆子 24. java反射机制加入的原因其实就是为了支持javabean 25. 比反射更方便的方法是使用内省类,其底层是以反射机制做驱动的,这样来看反射应该不止支持方法,还支持属性 26. 这篇servlet的教程很不错http://www.importnew.com/14621.html 27. oop的确对于现实世界的解释性更强,更能构建问题空间与解空间的映射,但是并非完全具有普适性的,某些必要的解空间元素无法映射到问题空间,某些问题空间元素无法在解空间构建出合适的模型 28. 包访问权限并不能囊括protected,因为包外的作用和private一样,即使继承了也不能访问 29. 在设计新类的时候,优先使用组合而非继承 30. java编程思想当中对于多态的解释感觉非常透彻,渐渐有点明白了,注意关键词 前期绑定 后期绑定 运行时解析 ,之后还需要更加深入的了解 31. 其实python当中也有多态啊,只不过python当中没有类型申明,直接对某个对象调用了某个方法,感觉这个和java当中是完全不同的?比如定义一个参数,函数内直接执行方法这种,其实就是多态,但也不是,因为你并非只能传该对象的子类,而是有这个名称方法的都行,正所谓鸭子类型。所以这也是我难以理解java多态的原因之一吧。 32. 什么是多态

<1>一种类型具有多种类型的能力
<2>允许不同的对象对同一消息做出灵活的反应
<3>以一种通用的方式对待个使用的对象
<4>非动态语言必须通过继承和接口的方式来实现
  1. python并不支持多态

注解

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述: “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。例如,在不使用鸭子类型的语言中,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误。任何拥有这样的正确的走和叫方法的对象都可被函数接受的这种行为引出了以上表述,这种决定类型的方式因此得名。 鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。从静态类型语言转向动态类型语言的用户通常试图添加一些静态的(在运行之前的)类型检查,从而影响了鸭子类型的益处和可伸缩性,并约束了语言的动态特性。

  1. 这篇文章对于理解python与java之间的区别很有帮助https://zhuanlan.zhihu.com/p/28155224,多态要解决的问题是如何便于多个相同类型对象的统一处理,由于python直接调方法就可以了,因此不会存在这个问题
  2. 泛型其实就是参数化类型
  3. new会将对象存储到堆当中,而基本类型会直接存储在堆栈当中,这样速度更快
  4. 关于java当中的内存泄露http://www.importnew.com/12961.html
  5. 基本类型没有初始化会有系统给定的默认值,而其他类型则均为null,那么基本类型的封装类型呢?和对象一致
  6. java的方法和python的方法有所不同,python的方法其实是绑定了对象参数的函数,当然定义的时候还是以函数的形式定义的,用对象调用的时候才是绑定的函数(也就是方法),而java当中则像是单纯的函数
  7. static的含义其实是方法或变量(域)不会和包含它的那个类的任何实例相关联
  8. 通常来说对于java一定要通过对象去调用非static方法,而在python当中则不一定要这样做,从这个角度上来看python在背后的一致性要比java更高,显得更加灵活,java则具有强制性
  9. 还有一个不同点——java当中可以通过实例去改变类变量,而python当中如果通过实例去改只会在该实例下创建一个新的同名实例变量。这种区别也是很正常的,因为java当中可以用static来区分实例变量和类变量,而python当中实例变量只能在初始化的时候定义,因而导致python当中的实例变量是可以任意创建的,这就导致通过实例对变量进行赋值是具有二义性的
  10. 关于java的编译过程 http://blog.csdn.net/cutesource/article/details/5904542
  11. java当中的==比较的是变量本身的值,对于基本类型来说就是实际值,而对于对象来说就是对象的地址。虽然.equals可以比较,但是其在object类当中的基本配置也是比较引用,只能通过重写这个方法来实现自己的比较方法
  12. java的构造器是没有返回值 而不是返回值为空
  13. 包含基本类型的参数表当中,如果传入的参数类型小于声明的形式参数类型,就会被提升
  14. 关于list和arrayList的区别所在http://blog.csdn.net/duanyipeng/article/details/7851138
  15. java中的可变参数和python一样,本质就是数组(列表)的解包
  16. java数组难用的地方就在于其创建的时候一定要规定大小,而list可以解决这个,虽然性能有所下降
  17. java对象没有那么强的可变和不可变的区分印记,这是因为基本类型并非对象,默认不可变,而唯一有争议的只有String对象,而String则和python中的str一样是不可变的,其他的自然没有什么可说的了
  18. 静态对象的初始化先于非静态对象,其初始化会在必要条件下进行(包括对象创建、静态对象引用和对应类的main方法执行是那种情况)
  19. 继承访问权限用于你希望被继承类用到,但是又不想让其他类使用
  20. 类是不可以是private的,如果不希望别人访问,可以对其构造器指定为private
  21. java当中,一般情况下为了继承会将所有方法设置为public,而将所有数据成员设置为private
  22. 创建一个导出类的对象的时候,该对象会包含一个基类的子对象,而这个子对象与用基类直接创建的对象是一样的,区别只在于后者来自于外部,而基类的子对象被包装在导出类对象内部。从这个层次上应当可以更加深入地理解继承的含义。所以在类初始化的时候总是会先进行基类的初始化,再进行子类的初始化。可以这样说,类的继承本质上就是暴露命名空间,子类的实例化本质上就是构造一个子类对象包裹一个积累对象,如果要调用方法或者调用值,只会向上递归查询。
  23. python当中应该和java当中不一样,也没有必要一样,毕竟python当中没有访问限制,这样的话全部摊开,继承就相当于拥有了父类的所有东西就行了。由于python当中必须使用self进行调用,这就导致暴露命名空间也不会有什么大问题。(同样,java由于一个类就是一个命名空间,也不会有问题)
  24. 代理挺有意思的,可以防止暴露出所有的方法,比如spaceship继承了spaceshipcontrol,那么就会有后者所有的方法,使用代理的手段可以在里面内置一个模块,然后通过调用这个模块的方式来暴露接口,很有意思啊。归根结底 能用代理还是因为两者的关系并非直观意义上的继承关系。
  25. 如果基类的默认构造器是带参构造器的话,子类必须对基类进行初始化
  26. protected是完全覆盖包访问权限的,不仅子类可以访问,包中的其他成员也是可以访问的
  27. 是否使用继承的关键是你的代码是否需要支持多态,如果不需要支持,那么继承并不是必要的(也不完全是,继承也是一种复用代码的手段,如果继承的目的是使用多态的话,那么子类就没有必要扩展方法,而只需要重写父类的方法就足够了。)所以继承有两个目的,一是进行方法扩展,二是进行方法重写,两种甚至可以分开来讨论。
  28. 编译器常量可以用final进行实现,其好处是一些计算可以在编译期间提前搞定
  29. 渐渐摸透java的继承了,就是一环一环往上,比如你调用一个方法,这个方法没有被重写,那么就会调用基类的,基类的这个方法如果调用了域,那么只会在基类层面以上进行搜索,如果调用了方法,那么就会重新从底层开始进行搜索,简而言之,其实域是没有重写的,而方法是有重写的。
  30. Java中的静态方法不能翻译成Python的类方法。哦,当然,他多多少少也能产生同样的效果,但类方法的目的实际上是做一些通常在Java中甚至都不可能的事情(如继承一个非默认的默认函数)。Java静态方法惯用的翻译通常翻译成一个模块级的函数,而不是一个类方法或静态方法。(并且静态常量应该翻译成模块级常量.)
  31. 在工厂模式当中,所谓的工厂就是用来创建其他对象的对象,calendar的getInstance就是工厂方法的一种应用
  32. java既然一般情况下无法继承基类的属性会不会导致某种不便?在python当中由于可以在构造方法当中调用父类的构造方法,而命名空间又没有隔离,所以是完全不会造成不便的
  33. 当你想要使接受某个接口作为参数的方法使用一个并没有实现某接口类对象作为参数的时候,可以使用适配器模式作为媒介,由于python当中是鸭子类型,因此就没有那么麻烦了(适配器模式可以算是对于Java没有鸭子类型机制的一种补偿)
  34. 策略模式的实现用到了多态的特性
  35. 类优先于接口优先于抽象类,不要增加不必要的抽象性
  36. 内部类的作用是为了实现多重继承http://blog.csdn.net/seebetpro/article/details/52059361
  37. Java是不太欢迎继承的。因为继承耦合度太高。比如你是一个人,你想会飞,于是就继承了鸟这个类,然后你顺便拥有了一对翅膀和厚厚的羽毛,可这些玩意你并不需要。所以Java发明了接口,以契约的方式向你提供功能。这其实是鸭子类型和强继承的一种中间形态。
  38. 我觉得我还要做的事情主要是两个
(1)要有一套设计逻辑的方法,千万不要卡在实现阶段
(2)不要过于依赖小心翼翼,而是要依赖归根结底解决问题的方法,比如直接把iml文件删除掉,这样就不会提交了
  1. 关于继承的设计,我感觉我自己还是存在误区的,一定要根据现实中的逻辑结构去进行设计,其实这是没有必要的,程序与现实并非一定需要完全对应的。因此用接口来设计可能比用继承来设计更好。
  2. 比较日期可以通过转成字符串来进行比较
  3. StringBuilder更快,但StringBuffer是线程安全的,如果需要在循环中拼接字符串 尽量不要使用普通的+
  4. java当中的RTTI(运行时绑定)是通过反射机制实现的
  5. 类是在其第一次使用的时候动态加载到JVM当中去的,所谓第一次使用指的是创建第一个对类的静态成员的引用(静态成员包括构造方法)
  6. 使用元组貌似可以代替简单的Data类型
  7. 原来可以用values方法来获取枚举的所有值啊。这个可以用一下,感觉非常方便
  8. 枚举类里的括号就是代表调用构造器,枚举其实是在枚举实例
  9. 注解是通过注解处理器进行运作的,注解处理器通过反射机制实现。可以通过class.getDeclaredMethods来获取类中的方法,通过method.getAnnotation来获取方法的注解。这样来看,注解的作用就是给方法或者域添加元信息,通过反射的机制在注解处理器当中可以提取这些元信息来加以运用
  10. String 的不变性的机制显然会在 String 常量内有大量的冗余。比如我创建一个循环,使字符'1'依次连接到'n',那么系统就得创建 n+(n-1) 个 String 对象。那有没有可变的 String 类呢?StringBuffer 类是可变的。它是 String 的对等类,它可以增加和编写字符的可变序列,并且能够将字符插入到字符串中间或附加到字符串末尾(当然是不用创建其他对象的,这里建议大家去看一看 String 类与 StringBuffer 类的区别,理解一下他们在内存中的存储情况)
  11. 使用 Class 类的静态方法 forName(String className),用类的名字获取一个Class实例。现在想来这个东西蛮有用的,可以根据各种配置文件进行实例化,如果用在python当中,写配置的时候不需要import这个import那个的,直接一个json,全部用字符串来表示就可以了,相当的方便
  12. JDBC是Java提供的一个操作数据库的API,而MyBatis是对JDBC的封装
  13. J2SE,全称为Java 2 Standard Edition。Java2平台包括:标准版(J2SE)、企业版(J2EE)和微缩版(J2ME)三个版本。J2SE即Java 2的标准版,主要用于桌面应用软件的开发。综上所述,将J2SE压缩一点再加上一些CLDC等方面的特性就是J2ME;将其扩充一点再增加一些EJB等企业应用方面的特性就是J2EE。
  14. error一般是指java虚拟机相关的问题,如系统崩溃、虚拟机出错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断,通常应用程序无法处理这些错误,因此应用程序不应该捕获Error对象,也无须在其throws子句中声明该方法抛出任何Error或其子类
  15. 除了RuntimeException及其子类以外,其他的Exception类及其子类都属于可查异常。对于这些异常都要在代码当中捕获,当然是在java当中。而对于运行时异常,可以选择捕获处理,这些异常是不应该出来的,要规避此类异常的产生。
  16. 常见RuntimeException:
ArrayStoreException 试图将错误类型的对象存储到一个对象数组时抛出的异常
ClassCastException 试图将对象强制转换为不是实例的子类时,抛出该异常
IllegalArgumentException 抛出的异常表明向方法传递了一个不合法或不正确的参数
IndexOutOfBoundsException 指示某排序索引(例如对数组、字符串或向量的排序)超出范围时抛出
NoSuchElementException 表明枚举中没有更多的元素
NullPointerException 当应用程序试图在需要对象的地方使用 null 时,抛出该异常
编译器对于很多运行时异常也是有提示的,之所以要叫做运行时异常是因为非运行时异常你如果不捕获是通不过编译的
  1. MyBatis提供了一种“半自动化”的ORM实现,是一种“SQL Mapping”框架。详细见https://www.shiyanlou.com/courses/802/labs/2798/document
  2. java bean的定义:
1、所有属性为private
2、提供默认构造方法
3、提供getter和setter
4、实现serializable接口
从这个角度来看我们项目中所有的data都是javabean(不过也有些data没有实现serializable接口)
  1. 关于xsi

注解

web-app是web.xml的根节点标签名称 version是版本的意思 xmlns是web.xml文件用到的命名空间 xmlns:xsi是指web.xml遵守xml规范 xsi:schemaLocation是指具体用到的schema资源 你不要看相关中文资料,看了就不明白了,schema就是schema~你把他翻译成对文档的限制就行了。你可能会说,dtd才是,实际上xsd和dtd是一样的

xsi是遵守的规范,而schemalocation是遵守的具体规范

  1. DTD简介:文档类型定义(DTD)可定义合法的XML文档构建模块(ibatis用的还是DTD而spring已经换xml schema)
  2. 通过序列化和反序列化可以实现对象的深拷贝
  3. 保留小数的技巧: String.format("%.1fk", 5.432)
  4. DAOException的确是继承了运行时异常,不需要进行捕获,之所以要叫做运行时异常是因为非运行时异常你如果不捕获是通不过编译的
  5. 为何要区分运行时异常和非运行时异常:应该是由于是常见错误,所以都处理的话代码会很麻烦,所以可以不进行预处理,想象下,所有的方法调用都有可能出现空指针,那么都try一下不是神经病么,所有的dao调用都有可能出错,如果都去写捕获逻辑,也太搞笑了。
  6. 可以使用基础类型来进行反序列化,如果没有值就是默认值,不会出现错误,其实规则都是这样,只不过非基础类型的默认值为null而已
  7. final其实是指变量与对象的绑定关系无法修改,那个对象自身还是可以改变的,其实也就是这个变量无法指向其他对象的意思吧
  8. 从依赖注入的角度来看,所有的组件其实都是注入进来的
  9. finally语句会先于return执行
  10. synchronized这个关键字是用于线程安全的,是给一个方法加锁,保证这个方法不会被并行调用
  11. 值为null的也可以进行强制类型转换
  12. 依赖注入不是万能的,就我目前的理解水平来看,依赖注入的构造参数只是在xml中配置的,无法在这种简单配置的基础上动态注入来替代层级间的参数传递(比如微信支付的那个问题,a依赖b,b依赖c,如果你想在a中改变c,这个是做不到的,就目前所知没有一次性重新构造一个c然后动态注入到b中去,让a来调用的方式,只能将参数从a到b到c一层层传递下去)
  13. 做参数类型兼容的时候注意那些非必要参数,之前直接强转是没有问题的,但是一但使用toString就要考虑一下空指针
  14. 归根结底synchronized就是锁对象,锁字符串通过itern保证同一个字符串只占用一个对象,但是在服务端多进程分布式的情况下这东西根本没有什么卵用,以后做magic tower java版的时候倒是可以使用一下
  15. java import jar是要在编译的时候-cp的,所以要import的jar在哪里并不重要,因为你-cp的时候是也写路径的。ide所谓的导入jar知识给你的项目与目标jar建立一种联系而已。这个机制貌似比python复杂很多,python引入外部库可以在固定的位置动态引入。java的话感觉就是打包一个程序。运行的时候连接所有依赖包,然后在需要依赖的时候根据包名去连接的依赖里面找就行了。其实很简单啊。由于自身所在的包也是依赖的一部分,和连接的依赖包没什么区别,只是不需要连接而已。
  16. class.forNmae的作用:返回一个给定类或者接口的一个Class对象,如果没有给定classloader,那么会使用根类加载器.如果initalize这个参数传了true,那么给定的类如果之前没有被初始化过,那么会被初始化.我们在JDBC第一步的时候,传入的参数是com.mysql.jdbc.Driver. 也就是说这个类会被初始化
  17. 关于arrayList和linkList的区别
(1)ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双向链表,有next也有previous)
(2)对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
(3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
  1. protected其实不能继承,而是子类可以访问
  2. 一个方法是抛出非受控异常代表调用者要检查参数,而如果抛出受控异常则表示该方法负责检查,也就是外层需要try catch

maven

  1. maven的使用是一定要配置版本号
  2. maven的依赖是层级依赖的,如果你用到的A库用依赖B库,那么你可以直接使用B库

tomcat

  1. 现在清楚tomcat的目录结构了 webapps目录下的内容都是可以访问的,root下的内容相当于主页,而其他文件夹下的内容则是不同路径下的,原来如此,其实url可以视作存储位置,只不过当初用flask的时候是直接做映射的,tomcat中基本的模式则是按照文件路径做映射的。
  2. Servlet为每个请求分配一个线程而不是进程
  3. 记一个坑,web.xml中的url-pattern配置改成 /* 之后可以使用了,之前使用 / 一直发现是有问题的
  4. tomcat的qps(每秒查询率)一般就只有几百,但是这个qps其实是由应用中的各种计算和数据库访问决定的,并非最多只有几百,简单的访问几万也是可以的

spring

  1. 自动装配并非所有的都装配,这个载体还是要通过context来加载的,然后该载体的组成部分是自动装配的
  2. spring默认是事务传播行为,即PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,就加入到这个事务中。
  3. cglib动态代理只能代理单独的类,而实现了接口的类需要使用jdk动态代理进行代理,jdk动态代理是通过接口实现的,而cglib动态代理则是通过子类实现的,而静态代理则是写死的装饰器模式
  4. spring-aop实现了aspectj的部分功能(或者说是xml配置功能),但如果要使用强大的动态代理和注解功能还是要使用aspectj
  5. 动态代理相较于静态代理的优势:解耦,通过参数就可以判断真实类,不需要事先实例化,更加灵活多变
  6. spring的方式不会出现bean的循环依赖,因为bean是注入进去的,所谓注入就像是给两个bean之间打开一条单向的管道,一出现有类型循环依赖的场景无非是管道编程双向的而已
  7. proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。首先说明下proxy-target-class=“true"和proxy-target-class="false"的区别,为true则是基于类的代理将起作用(需要cglib库),为false或者省略这个属性,则标准的JDK 基于接口的代理将起作用。

jvm

  1. JVM初始分配的堆内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的堆内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制。空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置-Xms、-Xmx 相等以避免在每次GC 后调整堆的大小。