用java也几年了,各种书籍电子文档也看了不少,java编程思想的电子书也看过,这次准备系统的在学习学习,巩固一下,顺便做个笔记。如有问题或者理解错误请大家指正,谢谢!
以下概括几个重点:
一.对象
对象,我的理解就是一类事务的具体抽象。例如:猪,房子。学习java的都知道一句名言,“万物皆对象”。就是在java的世界里所有的事务都能抽象成对象,抽象的好与坏决定了代码的质量。对象是一个概念,它的作用是用于我们分析需求,而后设计程序。
它的体现,简单点说,猪是一种动物,狗是一种动物,那在定义实体对象的时候,就会定义一个实体类:Pig和Dog。如果我们在深入的想想,猪和狗都是动物啊,他们都有很多相似的特性,比如:有头、眼睛;都会叫、跑等等。(当然如果有需要,可以将头抽象成一个对象,因为眼睛、耳朵等都是头上的属性)那我们抽象一个动物类:Animal,它里边都会定义很多动物的共同属性和行为。然后Pig和Dog就可以继承他们动物特有的属性和方法。
当然,我们“重写”了eat方法,因为猪和狗,吃东西不一样,猪不吃屎,狗会吃屎。额~~~我乱猜的。
二.“是一个”与“像是一个”
这是设计上的一个争论,例如一个制冷系统。起初这样设计:
空调“是一个”制冷系统,假设这个空调只能制冷,但是热力泵可以替代空调即“像是一个”制冷系统,而且还可以制热。但是对于制冷系统的调用者来说,它只知道有一个cool方法,而压根不知道有个制热功能。
当然,我们可以做一个通用的设计,系统不叫制冷系统,叫“温度控制系统”,这样做是不是更合理呢。但是又有一个问题,对空调来说,他只有一个制冷功能,但是也必须实现heat这个方法,即实现是空的。
这两种设计方式的使用,因情况而定,主要还是看需求。
三.上溯造型(向上转型)
继承和接口实现,有一个特点,父类可以当做子类对象来使用,但是只能调用父类定义的方法或属性。一般来讲,只有用到上溯造型时,才会用继承。
这在我们做程序设计的时候经常用到,尤其各种设计模式。这种面向接口的编程方式的好处就是,调用方面对的总是一类接口,而不关心它的实现,易于代码维护。
例如:上边的温度控制系统,一旦空调换成了热力泵,我只需要给他换一个热力泵。而对于调用温度控制系统的地方,不需要做任何的改动。
例如:策略模式
//温度控制系统
public interface TemperatureControlSystem {
public void helloWorld();
}
//空调实现
public class AirConditioner implements TemperatureControlSystem {
@Override
public void helloWorld() {
System.out.println("hello~~~~~AirConditioner");
}
}
//热力泵实现
public class HeatPump implements TemperatureControlSystem {
@Override
public void helloWorld() {
System.out.println("hello~~~~~ HeatPump ");
}
}
//调用方法
public class Context {
private TemperatureControlSystem strategy;
public Context(TemperatureControlSystem strategy) {
this.strategy = strategy;
}
public void doMethod(){
strategy.helloWorld();
}
public static void main(String[] args) {
Context c ;
c = new Context(new AirConditioner());
c.doMethod();
c = new Context(new HeatPump ());
c.doMethod();
}
}
在调用方法中,显而易见,我们只需要将new AirConditioner()换成new HeatPump ()就完成了我们冰箱与热力泵的兑换。
问题:为什么c = new Context(new AirConditioner());中传入的2个对象(虽然他们是实现的同一个接口),而确调用了正确的实现类的方法呢?
原因是,java中有一个机制叫做“绑定”。程序执行前的绑定叫“前期绑定”如:static,final,private(private也就是final的)。运行时绑定叫“动态绑定”。反正想一下就知道,对象转换过程中肯定绑定了真实对象的类型信息。
四.对象的生命周期
说对象的生命周期,先要讲对象创建。
当我们创建一个对象的时候,内存堆中会分配一些动态内存空间给他。对象创建常见方式2种:
int s=”111”;
Person p = new Person();
其中“s”和“p”都是对象的引用,他们是存放在栈内存中的,基本类型对象也都是存放在栈内存中的。“111”也是存放在栈内存中的。只有new出来的对象是存放在堆内存中的。
当一个对象的引用变为0的时候,意味着jvm可以清理它了。
堆栈详解见:http://www.cnblogs.com/whgw/archive/2011/09/29/2194997.html
五.初始化
初始化顺序
用new一个类来说明比较容易,比如:
public class Initialize {
private static Test t = new Test();
{
System.out.println("{}");
}
private int n=2;
static{
System.out.println("static{}");
}
public Initialize() {
System.out.println("initialize:Constructor");
System.out.println(n);
}
static{
System.out.println("static2{}");
}
public void f(){
System.out.println("f():execute");
}
public static void main(String[] args) {
new Initialize().f();
new Test2();
}
}
class Test{
public Test() {
System.out.println("Test:Constructor");
p();
}
public void p(){
System.out.println("Test:m");
}
}
class Test2 extends Test{
private int m=1;
public Test2(){
System.out.println("Test2:Constructor");
}
public void p(){
System.out.println("Test2:m:"+m);
}
}
/*
Test:Constructor
static{}
static2{}
{}
initialize:Constructor
2
f():execute
Test:Constructor
Test2:m:0
Test2:Constructor
*///:~
为什么m的输出会是0呢?因为子类重写了父类的p()方法,而创建子类对象之前,先要创建父类对象,但在父类对象的构造器中又调用了,被子类重写的方法p(),所以调用的是子类的p()方法,而这个时候子类Test2中的m还没有执行到被赋值的地方,所以编译器给了个初始值0。
统一类型的初始化都是按排列顺寻执行。
1.在其他任何事物发生之前,将分配给对象的存储空间初始化成二进制的零。(解释m为什么是0)
2.静态属性、静态块初始化
3.成员变量、基本块初始化
4.构造器初始化
5.局部变量初始化
六.垃圾回收机制
Java中的垃圾回收机制是一个神器,他帮助我们清理不用的对象,而我们不用手动的释放他们。
Jvm的垃圾回收机制只与堆内存打交道,即只管理new出来的对象。当jvm内存不够用时,垃圾回收机制才会运行,清理无用的垃圾对象。
垃圾回收方法原理
对于垃圾回收的方法有很多,常用的是“引用计数”和“标记清零”。这些知识只能帮助我们理解垃圾回收的机制,让我们更好的管理代码。实际的java虚拟机可能用的其他牛逼的方法。
引用计数法
每个对象都有一个引用计数器,当对象引用增加是加1,引用去除时或被置为null时减1。垃圾回收器在所有对象上遍历,当对象引用变为0时,就释放其占用的空间。这种方法的缺陷是,如果对象循环引用,则会出现“对象该被释放,但是引用不为0的情况”。这种方式用来说明垃圾回收的工作方式。
标记清理
这种收集器首先遍历对象图并标记可到达的对象,然后扫描堆栈以寻找未标记对象并释放它们的内存。这种收集器一般使用单线程工作并停止其他操作。并且,由于它只是清除了那些未标记的对象,而并没有对标记对象进行压缩,导致会产生大量内存碎片,从而浪费内存
标记-压缩收集器
有时也叫标记-清除-压缩收集器,与标记-清除收集器有相同的标记阶段。在第二阶段,则把标记对象复制到堆栈的新域中以便压缩堆栈。这种收集器也停止其他操作。
复制收集器
这种收集器将堆栈分为两个域,常称为半空间。每次仅使用一半的空间,JVM生成的新对象则放在另一半空间中。GC运行时,它把可到达对象复制到另一半空间,从而压缩了堆栈。这种方法适用于短生存期的对象,持续复制长生存期的对象则导致效率降低。并且对于指定大小堆来说,需要两倍大小的内存,因为任何时候都只使用其中的一半。
增量收集器
增量收集器把堆栈分为多个域,每次仅从一个域收集垃圾,也可理解为把堆栈分成一小块一小块,每次仅对某一个块进行垃圾收集。这会造成较小的应用程序中断时间,使得用户一般不能觉察到垃圾收集器正在工作。
分代收集器
复制收集器的缺点是:每次收集时,所有的标记对象都要被拷贝,从而导致一些生命周期很长的对象被来回拷贝多次,消耗大量的时间。而分代收集器则可解决这个问题,分代收集器把堆栈分为两个或多个域,用以存放不同寿命的对象。JVM生成的新对象一般放在其中的某个域中。过一段时间,继续存在的对象(非短命对象)将获得使用期并转入更长寿命的域中。分代收集器对不同的域使用不同的算法以优化性能。
finalize的用法
finalize方法是Object类的一个方法,多有的类都继承了它可以重写它。
finalize方法只在两种情况下调用,一种是jvm准备垃圾回收,会先调用它,还有就是手动调用System.gc()调用它;但是垃圾回收只和内存有关系,只有内存不够用的时候才会执行回收机制,而finalize或者将对象应用置为null都只是说明此对象可以被回收,但不一定就会被回收。对象引用置为null只是释放了在栈中的内存,并没有释放在堆中new的内存,堆中的内存由jvm垃圾回收控制。
使用垃圾收集器注意的地方
(1)每个对象只能调用finalize( )方法一次。如果在finalize( )方法执行时产生异常(exception),则该对象仍可以被垃圾收集器收集。
(2)垃圾收集器跟踪每一个对象,收集那些不可触及的对象(即该对象不再被程序引用 了),回收其占有的内存空间。但在进行垃圾收集的时候,垃圾收集器会调用该对象的finalize( )方法(如果有)。如果在finalize()方法中,又使得该对象被程序引用(俗称复活了),则该对象就变成了可触及的对象,暂时不会被垃圾收集了。但是由于每个对象只能调用一次finalize( )方法,所以每个对象也只可能 "复活 "一次。
(3)Java语言允许程序员为任何方法添加finalize( )方法,该方法会在垃圾收集器交换回收对象之前被调用。但不要过分依赖该方法对系统资源进行回收和再利用,因为该方法调用后的执行结果是不可预知的。
(4)垃圾收集器不可以被强制执行,但程序员可以通过调研System.gc方法来建议执行垃圾收集。记住,只是建议。一般不建议自己写System.gc,因为会加大垃圾收集工作量。
public class FinalizeTest {
@Override
protected void finalize() throws Throwable {
System.out.println("finalize called");
}
public static void main(String[] args) {
new FinalizeTest();
System.gc();
System.gc();
}
}
/*output:finalize called*///:~
七.异常
异常是java的又一个牛逼特点。它可以帮助我们在可能发生错误的地方“捕获”异常,防止出现代码卡死的情况;或者处理异常情况,保证代码的“异常流程”正确执行。
异常处理的方式改变了代码的编写方式:
代码一:
/**
* 1:正常;0:失败;-1:异常
* @return
*/
public int excute(){
try{
if(true){
return 1;
}else{
return 0;
}
}catch(Exception e){
return -1;
}
}代码二:
public void excute2(){
try{
System.out.println("execute");
}catch(Exception e){
throw new RuntimeException("出错了"+e);
}
}
在程序处理中,我们更愿意采用第二种方式,因为它可以很清楚的把后台错误“抛送”上来,以供前台处理。
注意:
如果在异常上抛过程中,有一层代理,那么就需要再代理中处理异常,然后再向上抛送一次,否则前台获取的错误会是代理异常,而不是底层的异常信息。
例如:
/**
*通用的限制适配器
*/
public <T> T getProxy(Class<T> intf, final T obj) {
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(),
new Class[] { intf }, new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
try{
Object result = method.invoke(obj, args);
return result;
}catch(Exception e){
throw e.getCause();
}
}
});
}
比如,此代理处理的是代码二中的excute2方法,那么在catch中,用throw e.getCause()方法将底层信息在抛送一次。这样在前台的异常信息就会是“"出错了"+e”;而不是java.lang.reflect.xxx的异常信息。
八.shis关键字
this关键字代表了对象本身,在一个类中是隐式存在的。就说说几个常用的形式。
shis构造器
/*这个类说明了2个问题,一个是this构造器,一个是创建子类对象的时候,必然先创建父类对象,
* 即在this(1),方法前边默认插入了一个super();
* 用IDE生成构造器的时候会自动加入,不知道大家注意过没有。*/
public class ExtemdThis extends Father{
int x;
public ExtemdThis() {
this(1);//这种调用必须在此方法中的第一样,否则报错。
super.p();
}
public ExtemdThis(int x) {
this.x = x;
}
public static void main(String[] args) {
System.out.println(new ExtemdThis().x);
}
}
class Father{
protected void p(){
System.out.println("Father");
}
}
/*
Father
1
*///:~
2.传递当前对象
//将当前对象传递给其他方法,为了显示我不是闲的蛋疼,在传递过程中对此对象做了一些处理,给x赋值。
public class PersonEatApple {
public void eat(Apple apple){
Apple peeled = apple.getPeeled();
System.out.println(peeled.x);
}
public static void main(String[] args) {
new PersonEatApple().eat(new Apple());
}
}
class Peeler{
static Apple peel(Apple apple){
apple.x=1;
return apple;
}
}
class Apple{
int x;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
Apple getPeeled(){
return Peeler.peel(this);
}
}
/*Output:
* 1
* *///:~
3.返回对象本身引用
//返回对象本身的引用,可以做到非常有趣的事情。
public class ReturnThis {
int i;
public ReturnThis increment(){
i++;
return this;
}
public static void main(String[] args) {
System.out.println(new ReturnThis().increment().increment().increment().i);
}
}
/*output:3
*///:~
4.javabean规范
//javabean中用于区分数据成员和参数名的区别,这算是一种规范。
public class JavaBean {
int x;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public JavaBean(int x) {
super();
this.x = x;
}
}
- 大小: 21 KB
- 大小: 16.2 KB
- 大小: 21.6 KB
分享到:
相关推荐
JAVA笔记1.pdf
java笔记java笔记java笔记java笔记java笔记java笔记java笔记
Java的设计理念是“一次编写,到处运行”,这意味着编写的Java程序可以在任何安装了Java虚拟机(JVM)的设备上运行。 #### 1.1 Java的特点 - **面向对象**:Java是一种纯粹的面向对象的语言,几乎所有的数据都是以...
Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习笔记Java学习...
本项目名为"Java笔记桌面程序",它是由一个热衷于编程的开发者为解决其所在公司无法使用网络笔记客户端的问题而自创的。这个程序采用Java语言编写,充分体现了Java的跨平台特性,可以在多种操作系统上运行,包括...
【宋红康java笔记】是一份综合性的Java学习资料,由知名编程教育者宋红康编撰。这份压缩包文件包含了大量的Java编程知识点,旨在帮助初学者和有经验的开发者深入理解和掌握Java语言的核心概念与高级特性。以下是根据...
专业的Java笔记可能会涉及这些内容,帮助学习者掌握Java的最新发展。 遗憾的是,由于【部分内容】部分不包含实际的笔记内容,无法进一步提供具体的编程示例和深入的解释。如果要学习Java,最好的方式是从学习Java的...
这份"非常好的java笔记"无疑是初学者踏入这个领域的宝贵资源。笔记由培训班的专业老师编写,内容详细且全面,旨在帮助初学者系统地学习和理解Java的基础知识。 首先,Java基础部分会涵盖变量、数据类型、运算符、...
【标题】"java读书笔记笔记笔记笔记笔记笔记" 暗示了这是一份关于Java编程语言的学习笔记,可能包含了作者在阅读Java相关书籍时所做的重要记录和理解。笔记通常涵盖了语言的基础概念、核心特性、类与对象、内存管理...
《狂神说Java笔记资料》是一份全面涵盖Java开发基础知识的文档集,旨在帮助学习者系统地掌握Java编程。这份笔记包含多个章节,每个章节都深入讲解了一个特定的主题,覆盖了从初学者到进阶开发者必备的知识点。 1. *...
【Java笔记内容概览】 1. **基础语法**:涵盖变量、数据类型、运算符、流程控制(条件语句、循环语句)、数组、字符串等基础知识。 2. **面向对象**:讲解类、对象、封装、继承、多态等核心概念,以及构造函数、...
Java学习笔记1 Java学习笔记1是学习Java过程中的笔记,主要记录了Eclipse开发环境中的快捷键使用、编辑功能、查找和调试等知识点。 Eclipse快捷键 Eclipse中有许多快捷键,掌握这些快捷键可以大大提高开发效率。...
"Java超强笔记"正是一份专为新手准备的学习资源,它全面涵盖了从Java环境的搭建到软件设计的各种概念,旨在提供一个易读且系统的学习路径。 首先,笔记可能会从Java的起源和发展开始介绍,让你了解这门语言的历史...
2020-4-6 java笔记 ---内部类 2020-4-6 java笔记 ---异常 2020-4-6 java笔记 --多线程 2020-4-8 java笔记 String类 2020-4-9 java 比较器 2020-4-10 java笔记 枚举类 2020-4-10 java 注解(Annotation) 2020-4-11 ...
全套java笔记整理,侧边栏目录结构方便查看,纯手工整理。达内笔记整理。 已整理成带侧边栏目录的网页结构,方便复习大纲和跳转查看。大部分都带有笔记代码。 (默认设置为深珊瑚蓝色调,不喜欢可以把配置文件里的...
1. **面向对象编程**:Java的核心概念之一,强调封装、继承、多态等特性。 2. **图形用户界面开发**:使用Swing或JavaFX等框架创建桌面应用。 3. **数据库编程**:连接数据库、执行SQL查询等操作。 4. **文件I/O流...
java笔记java笔记java笔记java笔记java笔记java笔记java笔记java笔记
1. 面向对象(OOP):Java的核心是面向对象编程,它将数据和操作数据的方法封装在一起,形成类。面向对象的三大特性——封装、继承和多态,在06面向对象(上)、07面向对象(中)和08面向对象(下)中进行了详细介绍...
详细的描述了java的基本知识,配合看java视频更好了。 笔记中有集合,泛型,线程,的详细案例,还有java.net的资料