Java学习笔记

来源:互联网 发布:炉石传说对网络要求 编辑:程序博客网 时间:2024/06/05 23:04

写Java有段时间了,一点点接触的东西多了,但是感觉浮于表面,理解得不够深刻,在这种状态下写代码不踏实,有必要梳理下相关知识,系统的学习下。
下面首先对Java知识做一个分类:

分类 知识点 基础原理 OOP、JVM、lambda 使用方法 基础语法、API、第三方类库、IDE、Debug工具 最佳实践 设计模式、优秀代码

1. 基础原理

1.1 OOP

Oracle官网上的教程对OOP的概念做了简单介绍:Object-Oriented Programming Concepts,有过编程经验的人对这些概念都不陌生。可是,为什么选择OOP?OOP有什么好处?有什么局限?
从逻辑电路-单片机-C语言-Java-Scala这一路学过来,最大的感觉是代码复用做得越来越好了,简单说就是更少的代码做更多的事。学习逻辑电路的时候得想着芯片每一个位的作用,实现一个加法都要记好标志位。到单片机的时候,数据存在寄存器和内存中,对数据的操作抽象成了一个个指令。不过写程序的时候得精心安排各种跳转,要记得保存现场,写个一两百行的程序就很不容易了,也就控制下电梯和彩灯。到了C语言,总的入口和出口还是在main函数这里,但是中间的代码被抽象成一个个函数,于是实现了指令集合的复用,不用写那么多的保存现场的代码。不过C语言里面有一个地方不太好,就是函数参数原来越多,多了之后呢就重构为struct,但是struct也越来越多不能很好的复用。到了Java这里,我们将数据和行为绑定到了一起,这个与我们认知世界的方式比较契合,因为我们就是通过一些属性和特定习性来对事物分类的。继承使得我们可以实现对struct的复用,但是对函数的复用就不那么好办了,虽然我们有接口、泛型,可以从一定程度上解决函数的复用,但总感觉存在一些限制,比如我们经常会写一些util类、help类,里面一般只有函数,最多就是一些常量,也就是说我们存在对行为本身的复用需求,行为不一定必须依附于数据。scala才刚刚开始用,顺便说两句,scala号称将面向对象和函数式编程结合起来了,也确实感觉到函数式编程的威力,省了很多for循环,不用太操心并发的问题。
以上只是一些经验之谈,不够深刻,还是找找大牛的文章看看。Object-oriented_programming 介绍了面向对象编程。里面引用了一篇文献,该文献分析了近40年的计算机文献,找到了OOP的比较流行的概念,依次是:继承、对象、类、封装、方法、消息传递、多态和抽象。原文如下:

Deborah J. Armstrong. The Quarks of Object-Oriented Development. A
survey of nearly 40 years of computing literature which identified a
number of fundamental concepts found in the large majority of
definitions of OOP, in descending order of popularity: Inheritance,
Object, Class, Encapsulation, Method, Message Passing, Polymorphism,
and Abstraction.

里面也讲到了很多对OOP的批评,最主要的还是认为OOP把事情搞复杂了。Erlang的主要设计者之一, Joe Armstrong说过:

The problem with object-oriented languages is they’ve got all this
implicit environment that they carry around with them. You wanted a
banana but what you got was a gorilla holding the banana and the
entire jungle.

嗯,总的说来,OOP降低了编程的门槛,不过呢容易把代码搞得太复杂。编程的初衷是降低重复劳动,不要走极端,怎么简单怎么来。

1.2 JVM

网上找到这篇文章 JVM学习笔记 ,图片比较多感觉不错,可以很快的带我回忆这方面的内容。之前买了《深入理解Java虚拟机》回来看,当时主要侧重于理解JVM的内存回收机制,但是看着看着就没耐心了。这次准备再温习一遍,主要目标是掌握JVM的调参技能。最后还是搜集下原始资料:
官方JVM说明文档-java8版
维基百科-Java virtual machine

1.3 Lambda

目前知道Lambda最大的特点是所有都是函数,然后是图灵完备的计算模型。
Oracle官网上找到的Lambda介绍
维基百科-Lambda calculus
lambda算子教程pdf

2. 使用方法

这部分主要关注轮子,轮子怎么造的。

2.1 基础语法

native java native关键字 意思是该方法由系统底层实现,java不管,通过native实现可移植。

static final 这两个的用法,在The Java® Language Specification 有明确说明,mark一下要多看看。

2.2 Java API

annotations 元数据,对代码的描述,可以理解为标签,本身对代码行为没有影响,需要依赖于compiler、jvm、运行代码中对注解的识别和处理。之前看了下ElementType、RetentionPolicy这两个枚举类型,对注解作用有一个大致了解,刚刚看了这个官网的教程,对注解使用也有了了解。注解可以理解为元数据,源数据应该是一些字段,但是java中确实用@interface来标识注解,而且里面是用函数的方法来实现字段的赋值取值功能。比较好奇java内部是怎么实现注解的,注解的这些值存储在什么地方?
Java Annotation原理分析(四) – 实现原理分析 讲了怎么定义自己的annocation,我知道了annocation与我们在某个时间点调用getAnnotation方法,然后做一些处理,这个对于我理解注解行为的生效时间点有很大帮助,但是仍然没有回到关于annocation在字节码中是怎么实现的问题。问题应该在放射上,放射是如何实现的,注解的内容是和类或者对象存储在一起吗?或者说对象的字节码中至少有一个字段用来存储他的注解的内容?
深入到class文件中去看getAnnotation内容,可以看到class中用
native byte[] getRawAnnotations();
存储原始的注解,然后用AnnotationParser来解析注解,AnnotationType告诉我注解的几个元素存在哪里。这里可以看到最终只返回了class本身声明的注解,以及class本身加继承自父类的注解,这里无法区分具体从哪一层的父辈继承来的注解。而且getAnnotation注解只解决了runtime时获取注解的问题,值域java文件编译成class文件,以及jvm解释class文件时怎么处理annocation的,需要具体去看compiler和jvm代码,不过以及可以大致猜到实现方式。

2.3 Guava

2.4 IDE

IntelliJ IDEA

2.5 Debug工具

debug工具

3. 最佳实践

这部分关注实际问题的解决方法。

3.1 OOP设计模式

3.2 第三方框架

最早看《Spring in Action(中文版)》接触到切面之类的概念,感觉特别神奇。工作之后公司里面用的spring,一般就是看到别人怎么写,自己就怎么写,也没太深究。去spring官网 喜欢给出各种案例工程,不太宣扬原理性的东西。
看了下spring的启动源码,所谓aop等功能的实现,其实主要依靠annocation。spring首先会读取xml格式的配置文件,初始化上下文,然后根据注解安排配置中bean的初始化。annocation加上xml,使得spring可以在xml中设置好参数,选择method的执行时机。
spring的api文档 可以看到api介绍。spring-beans-3.0.xsd 中介绍了xml的规范,这个需要一点 xml schema基础。
spring下面这段代码,有时间好好研究下。

@Override    public void refresh() throws BeansException, IllegalStateException {        synchronized (this.startupShutdownMonitor) {            // Prepare this context for refreshing.            prepareRefresh();            // Tell the subclass to refresh the internal bean factory.            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();            // Prepare the bean factory for use in this context.            prepareBeanFactory(beanFactory);            try {                // Allows post-processing of the bean factory in context subclasses.                postProcessBeanFactory(beanFactory);                // Invoke factory processors registered as beans in the context.                invokeBeanFactoryPostProcessors(beanFactory);                // Register bean processors that intercept bean creation.                registerBeanPostProcessors(beanFactory);                // Initialize message source for this context.                initMessageSource();                // Initialize event multicaster for this context.                initApplicationEventMulticaster();                // Initialize other special beans in specific context subclasses.                onRefresh();                // Check for listener beans and register them.                registerListeners();                // Instantiate all remaining (non-lazy-init) singletons.                finishBeanFactoryInitialization(beanFactory);                // Last step: publish corresponding event.                finishRefresh();            }            catch (BeansException ex) {                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);                // Destroy already created singletons to avoid dangling resources.                destroyBeans();                // Reset 'active' flag.                cancelRefresh(ex);                // Propagate exception to caller.                throw ex;            }        }    }
0 0
原创粉丝点击