基础
- Java编译后翻译成字节码,因此java程序与平台无关。
- 常量,在Java 中利用关键字final声明常量,习惯上常量全部用大写。
- 在Java 中,若期望某个常量在类中的多个方法中使用,通常将这些常量称为类常量。 使用关键字: static final
- &&和||是按照“短路”方式求值的,只要结果确定,后续的就不会再执行
- 在Math类中,包含了各种各样的数学函数。 Math.sqrt()
- string字符串的比较不能直接使用==,只会比较是否放置在同一位置上,要用相应的函数。
- null 是一个特殊的值,说明没有任何对象和该变量关联,并不是指对象为空。用length()==0和equal(““)判断是否是空字符串
- 尽量不要用char类型,是代码单元和编码的原因
- 不能在嵌套的块中定义相同的变量 {int n;{int n;}},这是存在错误的
如何查看异常产生的方法,遍历异常的堆栈
StackTraceElement[] st = daoExc.getStackTrace();
int j=0;
for (StackTraceElement stackTraceElement : st) {
String exclass = stackTraceElement.getClassName();
String method = stackTraceElement.getMethodName();
System.out.print(j++);
System.out.println(exclass);
System.out.println(method);
}
序列化
- Java序列化是指把Java对象保存为二进制字节码的过程,Java反序列化是指把二进制码重新转换成Java对象的过程。
- 那么为什么需要序列化呢?
- 第一种情况是:一般情况下Java对象的声明周期都比Java虚拟机的要短,实际应用中我们希望在JVM停止运行之后能够持久化指定的对象,这时候就需要把对象进行序列化之后保存。
- 第二种情况是:需要把Java对象通过网络进行传输的时候。因为数据只能够以二进制的形式在网络中进行传输,因此当把对象通过网络发送出去之前需要先序列化成二进制数据,在接收端读到二进制数据之后反序列化成Java对象。
string
- Java string是不可变字符串,也就是说string是无法改变的,所有针对string的改变,都是先分配空间,然后拷贝的过程。
- 与string是不可变字符串对应的一个知识点就是,一个string对象,不仅包括内容,也包括其存储的地址。因此“==”比较字符串,不仅是比较内容,也比较了地址,只有同一个对象才会相等。如果相比较内容,用equals函数比较:”bi“.equals("")。
工厂方法模式
- 工厂方法模式有很多变形,其实本质的作用是一致的,就是负责生产相应的类对象。这样做的部分好处是,对象生产的接口是统一的,而且还可以记录相应的生产的对象的相关信息。
Java Servlet
- Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
MVC
- 模型-视图-控制器(MVC)是在计算机上实现用户界面的软件架构模式。它将一个给定的应用程序分成三个相互关联的部分。这样做是为了将信息的内部表示与信息呈现给用户并让用户接受的方式分离开来。MVC设计模式分离了这些主要成分并允许高效的代码重用和并行开发。
redis mysql
- redis和mysql要根据具体业务场景去选型
- mysql:数据放在磁盘
- redis:数据放在内存
- redis适合放一些频繁使用,比较热的数据,因为是放在内存中,读写速度都非常快,一般会应用
在下面一些场景。- 排行榜
- 计数器
- 消息队列推送
- 好友关注,粉丝
- redis和mysql各自的一些特点
- redis只是缓存,不是数据库如mysql,所以redis中有的数据库,mysql中一定有。
- 用户请求先去请求redis,如果没有,再去数据库中去读取。
- redis中缓存一些请求量比较大的数据(这些缓存数据,mysql中一定也是有的),没必要所有数据都
缓存到redis中。 - 之所以从缓存中拿数据会快,是因为缓存的数据存在于内存中,不像mysql的数据是存在磁盘上的,即
不用经过从磁盘加载到内存这个过程(这个过程是非常耗时和低效的),直接从内存获取数据。 - 当redis缓存崩溃的时候,那么不是海量的请求都去访问数据库了?数据库能抗住吗?
Java Bean
- Javabean没啥高大上的。就是满足一定规范的Java类而已。类必须是public的、属性是private的、有无参数的构造方法、有getter和setter方法、实现java.io.serializable接口的就叫Java bean(感觉这一项无所谓)至于这么做的目的:方便别人调用你的类,比如spring框架autowired。
java对象 POJO和JavaBean的区别
- POJO
"Plain Ordinary Java Object",简单普通的java对象。主要用来指代那些没有遵循特定的java对象模型,约定或者框架的对象。
POJO的内在含义是指那些:- 1.有一些private的参数作为对象的属性,然后针对每一个参数定义get和set方法访问的接口。
- 2.没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的java对象。
- JavaBean
JavaBean 是一种JAVA语言写成的可重用组件。JavaBean符合一定规范编写的Java类,不是一种技术,而是一种规范。大家针对这种规范,总结了很多开发技巧、工具函数。符合这种规范的类,可以被其它的程序员或者框架使用。它的方法命名,构造及行为必须符合特定的约定:- 1.所有属性为private。
- 2.这个类必须有一个公共的缺省构造函数。即是提供无参数的构造器。
- 3.这个类的属性使用getter和setter来访问,其他方法遵从标准命名规范。
- 4.这个类应是可序列化的。实现serializable接口。
- 5.因为这些要求主要是靠约定而不是靠实现接口,所以许多开发者把JavaBean看作遵从特定命名约定的POJO。
- 两者有什么区别
- 1.POJO其实是比javabean更纯净的简单类或接口。POJO严格地遵守简单对象的概念,而一些JavaBean中往往会封装一些简单逻辑。
- 2.POJO主要用于数据的临时传递,它只能装载数据, 作为数据存储的载体,而不具有业务逻辑处理的能力。
- 3.Javabean虽然数据的获取与POJO一样,但是javabean当中可以有其它的方法。
一个简单的设计原则
- 名词皆对象:当面对一个项目,做系统设计时,第一个问题就是,系统里要设计哪些类?最简单的办法就是,把要设计系统的名词提出来,通常,名词可设计为对象,但是否所有名词都需要设计对应的类呢? 要具体问题具体分析.不是不可以,是否有必要.有时候需要把一些动词名词化, 看看现实生活中, 写作是动词,所有写作的人叫什么? 没有合适的称呼,我们就叫作者, 阅读是动词,阅读的人就称读者. 中文通过加"者","手"使动词名词化,舞者,歌手,投手,射手皆是这类.
依赖注入的理解
控制反转和依赖注入
- A类的实现依赖B类,如果在A类的内部实现B类会造成紧耦合,程序易出错,难维护。解耦的一种方案就是将控制权剥离出来,交给第三方,这就叫控制反转(IOC,Inversion ,Of Control)。控制反转是一种思想,而依赖注入(DI, Dependency Injection)是其最典型的实现方法。由第三方(我们称作IOC容器)来控制依赖,把他们通过构造函数、属性或者工厂模式等方法,注入到类A内,这样就极大程度的对类A和类B进行了解耦。
- Spring 能有效地组织J2EE应用各层的对象。不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的管理下有机地协调、运行。Spring将各层的对象以松耦合的方式组织在一起,Action对象无须关心Service对象的具体实现,Service对象无须关心持久层对象的具体实现,各层对象的调用完全面向接口。当系统需要重构时,代码的改写量将大大减少。
- 上面所说的一切都得宜于Spring的核心机制,依赖注入。依赖注入让bean与bean之间以配置文件组织在一起,而不是以硬编码的方式耦合在一起。理解依赖注入
- 依赖注入(Dependency Injection)和控制反转(Inversion of Control)是同一个概念。具体含义是:当某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个Java实例,被调用者)的协助时,在 传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在Spring里,创建被调用者的工作不再由调用者来完成,因此称为控制反转;创建被调用者 实例的工作通常由Spring容器来完成,然后注入调用者,因此也称为依赖注入。
依赖注入和实例化的区别
- 实例化的缺点就是,一个基类或则接口对象实例化的时候,必须指定实现类。如果后续构建了其他的实现类,就需要逐一在使用到的地方更改代码,使用依赖注入,可以很好得规避这些问题。
自动注入的两个注解
- 1.@Autowired
- 默认按类型装配(这个注解是属业spring的),默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:
如果我们想使用名称装配可以结合@Qualifier注解进行使用,如下:Java代码@Autowired(required=false)
@Qualifier 的另一作用是当一个接口存在两个实现类的时候,用其指定其中的实现类@Autowired() @Qualifier("baseDao") private BaseDao baseDao;
- 2.@Resource
- @Resource 是JDK1.6支持的注解,默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找,如果注解写在setter方法上默认取属性名进行装配。当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。
- @Resource可以作用于字段和函数上。当作用于字段上的时候,如果我们只是简单的这样写
这时候spring注入p的过程是 (a).先查找xml中是否有id为p的元素 (b).如果没有找到,则看是否有name属性(@Resource name=“”),有则查找name (c).否则查找PersonDao类型的元素@Resource PersonDao p;
@Autowired注解是根据类型进行查找,比如PersonDao p,他会去xml文件里查找类为PersonDao的元素。 - 3.区别
- 如果要字段注入,使用@Resource;要构造方法注入,使用@Autowired。其实实际开发中个人觉得没什么区别。
注解
什么是注解
- Java注解又称为标注,是Java从1.5开始支持加入源码的特殊语法元数据;Java中的类、方法、变量、参数、包都可以被注解。这里提到的元数据是描述数据的数据。
- 注解仅仅是元数据,和业务逻辑无关,所以当你查看注解类时,发现里面没有任何逻辑处理;注解的逻辑实现是元数据的用户来处理的,注解仅仅提供它定义的属性(类/方法/变量/参数/包)的信息,注解的用户来读取这些信息并实现必要的逻辑。当使用java中的注解时(比如@Override、@Deprecate、@SuppressWarnings)JVM就是用户,它在字节码层面工作。如果是自定义的注解,比如第三方框架ActiveAndroid,它的用户是每个使用注解的类。
一些常用的注解
- @Component, @Service, @Controller, @Repository 是spring注解,注解后可以被spring框架所扫描并注入到spring容器来进行管理。
- @Component是通用注解,其他三个注解是这个注解的拓展,并且具有了特定的功能
- @Repository注解在持久层中,具有将数据库操作抛出的原生异常翻译转化为spring的持久层异常的功能。
- @Controller层是spring-mvc的注解,具有将请求进行转发,重定向的功能。
- @Service层是业务逻辑层注解,这个注解只是标注该类处于业务逻辑层。
用这些注解对应用进行分层之后,就能将请求处理,义务逻辑处理,数据库操作处理分离出来,为代码解耦,也方便了以后项目的维护和开发。
注解的作用
- 格式检查:告诉编译器信息,比如被@Override标记的方法如果不是父类的某个方法,IDE会报错;
- 减少配置:运行时动态处理,得到注解信息,实现代替配置文件的功能;
- 减少重复工作:比如第三方框架xUtils,通过解@ViewInject减少对findViewById的调用,类似的还有(JUnit、ActiveAndroid等);
面向切面编程
什么是切面编程
- 这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
AOP
- 面向切面编程(AOP是Aspect Oriented Program的首字母缩写) ,我们知道,面向对象的特点是继承、多态和封装。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。
- 但是人们也发现,在分散代码的同时,也增加了代码的重复性。什么意思呢?比如说,我们在两个类中,可能都需要在每个方法中做日志。按面向对象的设计方法,我们就必须在两个类的方法中都加入日志的内容。也许他们是完全相同的,但就是因为面向对象的设计让类与类之间无法联系,而不能将这些重复的代码统一起来。
- 也许有人会说,那好办啊,我们可以将这段代码写在一个独立的类独立的方法里,然后再在这两个类中调用。但是,这样一来,这两个类跟我们上面提到的独立的类就有耦合了,它的改变会影响这两个类。那么,有没有什么办法,能让我们在需要的时候,随意地加入代码呢?这种在运行时,动态地将代码切入到类的指定方法、指定位置上的编程思想就是面向切面的编程。
- 一般而言,我们管切入到指定类指定方法的代码片段称为切面,而切入到哪些类、哪些方法则叫切入点。 有了AOP,我们就可以把几个类共有的代码,抽取到一个切片中,等到需要时再切入对象中去,从而改变其原有的行为。这样看来,AOP其实只是OOP的补充而已。OOP从横向上区分出一个个的类来,而AOP则从纵向上向对象中加入特定的代码。有了AOP,OOP变得立体了。如果加上时间维度,AOP使OOP由原来的二维变为三维了,由平面变成立体了。从技术上来说,AOP基本上是通过代理机制实现的。AOP在编程历史上可以说是里程碑式的,对OOP编程是一种十分有益的补充。
进程和线程
进程和线程的区别
- 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。
- 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。
IOC容器中的Bean
- Singleton:一个Spring容器中只有一个Bean的实例,这是Spring的默认配置,全容器共享一个实例。这种情形下,思考多个线程调用一个Bean的场景:Bean对象尽量不能保留状态、否则要保证线程安全。方法的本身如果没有依赖其他资源或是静态对象,可以被多个线程安全调用,因为方法依赖栈数据,而线程之间栈是独立的。
- 调用一些组件的时候,