Java基础
2024-06-10 18:30:07 13 举报
AI智能生成
Java基础是Java编程语言的核心内容,涵盖了变量、数据类型、运算符、条件语句、循环结构、数组、函数、类、对象和异常处理等方面的知识。Java文件通常以.java为扩展名,且需要经过编译和运行两个步骤。Java语言具有跨平台、面向对象、分布式、多线程、安全等特点,被广泛应用于web开发、移动应用开发、大数据处理和科学计算等领域。
作者其他创作
大纲/内容
面向对象编程(基础部分)
类与对象
类和对象的区别和联系<br><ul><li>类是抽象的,概念的,代表一类事物,它是一种数据类型。</li><li>对象是具体的,实际的,代表一个具体事物。</li><li>类是对象的模板,对象是类的一个个体,对应一个实例。</li></ul>
对象在内存中的存在形式
注意细节:<br><ol><li>创建对象,首先将Cat类信息(属性和方法信息,只会加载一次)加载到方法区。</li><li>然后在堆中分配空间,进行默认初始化,如属性类型为int 是0。</li><li>继而把地址赋给cat(对象引用),cat会指向对象。</li><li>最后进行指定初始化,即对属性进行赋值(根据类型,决定是否开辟空间..)。</li></ol>
java内存的结构分析<br>栈:一般存放基本数据类型(局部变量)<br>堆:存放对象(Cat cat,数组等)<br>方法区:常量池(常量,比如字符串),类加载信息<br>
类与对象
属性(成员变量)<br>
基本介绍:<br>概念或者叫法上,成员变量、属性,field都可以。<br>属性是类的一个组成部分,一般是基本数据类型,当然也可以是引用类型,如对象,数组。
注意事项和细节<br><ul><li>属性的定义语法同变量:访问修饰符 属性类型 属性名;</li><li>属性的定义类型可以为任意类型,包含基本类型和引用类型;</li><li>属性如果不赋值,有默认值,规则和数组一致。</li></ul>
如何创建对象
先声明,在创建。
直接创建。<br>Cat cat=new Cat();
如何访问属性
基本语法:对象名.属性名;
成员方法
方法引入及调用机制分析
成员方法的功能【为什么要有方法】:<br><ul><li>提高代码的复用性。</li><li>可以将实现的细节封装起来,然后供其他用户调用即可。</li></ul>
方法定义:<br><ol><li>形参列表:表示成员方法输入。</li><li>返回数据类型:表示成员方法输出,void表示没有返回值。</li><li>方法主体:表示为了实现某一功能代码快。</li><li>return: 有返回值时,必须有。没有返回值时,可以有,但后面不能加返回值,如return ;(此时没有意思,一般省略)</li></ol>
注意事项和使用细节<br><ol><li>一个方法只有一个返回值。</li><li>返回类型可为任意类型,基本类型,引用类型都可以。</li><li>有返回数据时,必须有return,返回值类型必须一致或兼容。</li><li>方法名:建议驼峰法,见名知意。</li><li>方法是有修饰符的,用来表明方法可供使用的范围,共4种(后面细讲)</li><li>使用方法时,形参和实参,保持一致,类型一致或兼容,个数,顺序必须一致。</li><li>方法体内不能在定义方法,即不能嵌套定义。方法内可以进行方法调用。</li></ol>
方法的调用:<br><ul><li>同类方法,直接调用。</li><li>不同类方法,对象名调用。跨类的方法调用还与方法的修饰符有关,后面详讲。</li></ul>
成员方法传参机制
基本类型数据,传递的是值(值拷贝),形参的任何改变不影响实参。
引用数据类型,传递的是引用(也可以说是值,这个值是地址),可以通过形参影响实参。
递归
基本介绍:<br>简单的说:递归就是方法自己调用自己,每次调用时传入不同的变量。递归有助于编程者解决复杂问题,同时可以让代码变得简洁。
递归能够解决的问题
递归在内存中的运行机制
递归重要规则:<br><ol><li>执行一个方法时,就创建一个新的受保护的独立空间(栈空间)</li><li>方法的局部变量是独立的,不会相互影响,前提是基本数据类型。如果是引用类型比如数组、对象,就会共享该引用类型的数据。</li><li>递归必须向退出递归的条件逼近,否则就会无限递归,出现stackOverflowError.</li><li>当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用就将结果返回给谁。</li></ol>
经典案例:阶乘、斐波那契数列、老鼠出迷宫(二维数组,递归)、汉诺塔、八皇后<br>这几个案例,由浅入深,尤其是老鼠出迷宫后3个,还是可以深入研究一下的。
重载(overload)
基本介绍:<br>java中允许同一类中,多个同名方法的存在,但要求形参列表不一致。<br>好处:减轻了起名、记名的麻烦。
注意事项和使用细节:<br><ol><li>方法名:必须相同。</li><li>参数列表:必须不同(参数类型或个数或顺序,至少有一样不同,参数名无要求)。</li><li>返回类型:无要求。</li></ol>
可变参数
基本概念:<br>java允许将同一个类中多个同名同功能但参数个数不同的方法,封装成一个方法。
基本语法:<br>访问修饰符 返回类型 方法名(数据类型... 形参名){}
注意事项和使用细节:<br><ol><li>可变参数的实参可以为0或任意多个。</li><li>可变参数的实参可以为数组,它的本质就是数组。</li><li>一个形参列表中只能出现一个可变参数,且必须在参数的最后一个(可变参数可以和普通类型的参数一起放在形参列表)。</li></ol><br>
作用域
基本使用:(变量作用域)<br>java编程中,主要的变量就是属性(成员变量)和局部变量(一般是指成员方法中定义的变量)。<br>作用域的分类:<br>全局变量:也就是属性,作用域为整个类体。<br>局部变量:除了属性之外的其它变量,作用域为定义它的代码块中。<br><font color="#ff0000">全局变量可以不赋值,直接使用,因为有默认值,局部变量必须赋值后,才能使用,因为没有默认值。</font>
作用域:注意事项和细节使用<br><ol><li>属性和局部变量可以重名,访问时遵循就近原则。</li><li>在同一个作用域中,比如同一个成员方法中,两个局部变量,不能重名。</li><li>属性生命周期较长,伴随着对象的创建而创建,伴随着对象的死亡而死亡。局部变量,生命周期较短,伴随它的代码块的执行而创建,伴随着方法的结束而死亡,即用在一次方法调用过程中。</li><li>作用域不同:全局变量,可以被本类使用,或其它类使用(通过对象调用)局部变量,只能在本类中对应的方法的使用。</li><li>修饰符不同:全局变量【属性】可以加修饰符。局部变量不可以加修饰符。</li></ol>
构造器
基本介绍:<br>构造方法又叫构造器,是类的一种特殊的方法,它的主要作用是完成对新对象的初始化。<br>特点:<br>方法名和类名相同。<br>没有返回值。<br>在创建对象时,系统会自动的调用该类的构造器完成对象的初始化。
基本语法:修饰符 方法名(形参列表){方法体;}<br><ol><li>构造器的修饰符可以默认;</li><li>构造器没有返回值;</li><li>方法名和类名字必须一样;</li><li>参数列表和成员方法一样的规则;</li><li>构造器的调用由系统完成。</li></ol>
注意事项和使用细节:<br><ul><li>一个类可以定义多个不同的构造器,即构造器重载。</li><li>构造器是完成对象的初始化,而不是创建对象。</li><li>如果没有定义构造方法,系统会自动生成一个默认无参构造方法。可通过javapz指令反编译.class文件查看。一旦定义之后,就不会有默认的无参构造方法了,如果想使用,需要手动添加。</li></ul>
javap 了解,javap hello.class 可以查看源码。如果想查看其他信息,可添加相关指令,如-c,-v等。
对象创建初始化流程分析<br><li>加载person类信息(Person.class),只会加载一次。</li><li>在堆中分配空间(地址)。</li><li>完成对象初始化1默认初始化age=0 name=null 2显示初始化 age=90 name=null 3构造器初始化 age=20,name=小倩</li><li>将对象在堆中的地址,返回给p(p是对象名,也可以理解为对象引用。)</li>
心得:看到这部分,这些设计的东西,是有一定规律或者说法的,不是想当然来的。比如,默认一个无参构造,是为了满足基础的对象创建,如果定义了新的构造方法,自然不需要默认定义(可有可无)。 在无参构造的语法设计上,没有返回值,且不需要写void,这样只通过此处,就能给普通方法区分。 再加上与类名相同,这样系统调用构造器的时候,可以直接匹配上对应构造器。 构造器通过重载,来满足多种需要。 很巧妙。
this
什么是this?<br>java虚拟机会给每个对象分配this,代表当前对象。<br>主要解决问题:<br>使用this解决构造器中变量命名问题。
感觉图上画的有些乱,可以认为this是堆中对象的一个属性即可。相比于生活中我的用法。
this关键字的注意事项和使用细节<br><ol><li>this关键字可以用来访问本类的属性、方法、构造器。</li><li>this用于区分当前类的属性和局部变量。</li><li>访问成员方法的语法:this.方法名(参数列表);</li><li>访问构造器语法:this(参数列表);注意只能在构造器中使用,且放在第一行。</li><li>this不能在类定义的外部使用,只能在类定义的方法中使用。</li></ol>
习题思考:用Double作返回数据类型,可以接收null。解决double接受返回值的局限性。
面向对象编程(中级部分)
IDEA
IDEA介绍:<br><ol><li>全称intellij Idea</li><li>业界被公认最好的Java开发工具</li><li>是jetBrains公司的产品,该公司总部位于捷克的首都布拉格</li><li>除了支持java,还支持html,css,php,mysql,python</li></ol>
ide(集成开发环境)其他工具-eclipse<br><ol><li>eclipse是一个开放源代码的,基于java的可扩展开发平台。</li><li>最初由ibm公司耗资3000万美金开发的下一代ide开发环境。</li><li>2001年11月贡献给开源社区。</li><li>是目前最优秀的java开发ide之一。</li></ol>
下载、安装
背景、字体设置等。
常用快捷键,可自定义键。settings->keymap<br><ol><li>删除当前行,复制当前行,补全代码,取消注释,自动导入类,快速格式化,快速运行,快速生成构造方法等。</li><li>查看类层级关系: ctrl+h;</li><li>查看方法: ctrl+b;</li></ol>
自定义模板:<br>file->settings->editor->live templates->
常用插件
codota代码智能提示插件
打出首字母就能联想出一整条语句,还显示了每条语句的使用频率。
key promoter x快键键提示插件
每次都会在右下角弹窗提示,帮助快速熟悉快捷键。
codeglance 显示代码缩略图插件
lombok 简化臃肿代码插件
alibaba java coding guidelines 阿里巴巴代码规范检查插件
sonarlint代码质量检查插件
包
三大作用:<br><ol><li>区分相同名字的类。</li><li>当类很多时,方便管理。如api文档。</li><li>控制访问范围。</li></ol>
基本语法:package com.bear;<br>pachage 关键字,表示打包。<br>com.bear 包名。
包的本质:<br>创建不同的文件夹来保存类文件。
包的命名<br>命名规则:数字、字母、下划线,数字不能开头,不能是关键字或保留字。<br>命名规范:一般是小写,公司名、项目名、业务模块名;
常用包:<br>java.lang.* 基础包,默认引用。<br>java.util.* 工具包,如scanner。<br>java.net.* 网络包。<br>java.awt.* 界面开发包,GUI。
注意事项和使用细节:<br><ol><li>package的作用是声明当前类所在的包,需要放在类的最上面,一个类中最多只有一句package;</li><li>import指令 位置放在package的下面,在类定义前面,可以有多句且没有顺序要求。</li></ol>
访问修饰符
基本介绍:<br>java提供四中访问控制修饰符号,用来修饰控制方法和属性(成员变量)的访问控制权限。<br><ol><li>公开级别:public 修饰,对外公开。</li><li>受保护级别:用protected修饰,对子类和同一包中的类公开。</li><li>默认级别:没有修饰符号,向同一个包的类公开。</li><li>私有级别:用private修饰,只有类本身可以访问,不对外公开。</li></ol>
使用注意事项:<br><ol><li>修饰符可以用来修饰类中的方法和属性,还可以修饰类(不过只有默认和public两种,遵循上面访问特点)。</li><li>方法的访问规则和属性完全一样。</li></ol>
封装
基本介绍:<br>封装就是把抽象出来的数据【属性】和对数据的操作【方法】封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作【方法】,才能对数据进行操作。
封装的理解和好处<br><ol><li>隐藏实现细节。</li><li>可以对数据进行验证,保证安全合理。</li></ol>
封装的实现步骤:<br>将属性进行私有化private[不能直接修改属性]<br>提供一个公共的set方法,用于对属性判断并赋值<br>public void setXxx(类型 参数名){<br>//加入数据验证的业务逻辑<br>属性=参数名;<br>}<br>提供一个公共的get方法,用于获取属性的值<br>public XX getXxx(){<br>return xx;<br>}
继承
继承基本介绍<br>继承可以解决代码复用,让我们的编程更加接近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继承父类即可。<br>
继承的基本语法<br>class 子类 extends 父类{}<br><ol><li>子类就会自动拥有父类定义的属性和方法。</li><li>父类又叫超类,基类。</li><li>子类又叫派生类。</li></ol>
使用细节:<br><ol><li>子类继承了所有的属性和方法,在子类中私有属性是不能直接访问的,可以通过公共的方法去访问。</li><li>子类必须调用父类的构造器,完成父类的初始化。</li><li><font color="#ff0000">当创建子类对象时,不管使用子类的哪一个构造器,默认情况下总是会调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super显示的去指定使用父类的哪一个构造器完成父类的初始化工作,否则编译器不会通过。</font></li><li>如果希望指定调用父类的哪一个构造器 ,可显示调用。</li><li>super使用时,需要构造器第一行。</li><li>super和this都只能放在构造器第一行,因此这两个方法不能共存在一个构造器中。</li><li>java所有类都是object的子类,object是所有类的基类。</li><li>父类构造器的调用不限制于直接父类,将一直往上追溯到object类。</li><li>子类最多只能继承一个父类(直接继承),即java中是单继承机制。</li><li>不能滥用继承,子类和父类之间必须满足is-a的逻辑关系。</li></ol>
super关键字
基本介绍:super代表父类的引用,用于访问父类的属性、方法、构造器。
基本语法:<br>访问父类的属性,方法,都不能访问带有private修饰。用super.调用。<br>访问父类构造器:只能放在构造器的第一句,且只能有一句。
使用的好处与细节<br>好处:分工明确,父类属性由父类初始化,子类属性由子类初始化。<br>当子类和父类的成员(属性和方法)重名时,为了访问父类的成员,必须使用super。如果没有重名,使用super,this,直接访问效果是一样的(这是针对访问的成员在父类中)。<br>super方法不限定直接父类,间接父类也可以。遵循就近原则:A->B->C
super与this
方法重写【覆盖】
基本介绍:简单说,方法重写就是子类有一个方法,和父类(包含间接父类)的某个方法(名称,返回类型,参数)一样,那么就说这个子类的方法重写了父类的方法。
注意事项和细节:<br><ol><li>子类的方法的参数、方法名称,和父类完全一样。</li><li>子类的返回类型与父类一样,或者是父类返回类型的子类。</li><li><font color="#ff0000">子类方法不能缩小父类方法的访问权限。</font></li></ol>
方法重写与重载的对比
多态
多态基本介绍<br>方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础上的。
多态的具体体现
方法的多态:重写和重载的体现。
对象的多态:<br>一个对象的编译类型和运行类型可以不一致,编译类型在定义对象时就确定了,运行类型是可以变化的(在运行时确定)。编译看左边,运行看右边。 Animal animal= new Dog();
多态注意事项和细节<br>多态的前提:两个对象存在继承关系。<br>
多态的向上转型:<br><ol><li>本质:父类的引用指向了子类的对象。</li><li>语法:父类类型 引用名= new 子类类型();</li><li>特点:编译类型看左边,运行类型看右边。</li></ol>可以调用父类中的所有成员(遵守访问权限)。<br>不能调用子类中的特有成员(在编译阶段能调用哪些成员,是由编译类型来决定的)。<br>最终运行效果看子类的具体实现!
多态的向下转型:<br><ol><li>语法:子类类型 引用名=(子类类型)父类引用。</li><li>只能强转父类的引用,不能强转父类的对象。</li><li>要求父类的引用必须指向的是当前目标类型的对象(把Dog强转给Animal,不能用Cat接收)。</li><li>可以调用子类类型中的所有成员(满足编译阶段调用成员的原则)。</li></ol>
属性没有重写直说,属性的值看编译类型。
instanceOf比较操作符,用于判断对象的<font color="#ff0000">运行类型</font>是否为xx类型或是其子类型。
动态绑定机制<br><ol><li>当调用对象的方法时,该方法会和对象的内存地址【运行类型】绑定。</li><li>当调用对象的属性时,没有动态绑定机制,哪里声明,哪里使用。</li></ol>
Object类详解
equals方法:==和equals的对比<ol><li>==:既可以判断基本类型,又可以判断引用类型。</li><li>==:如果判断基本类型,判断的是值是否相等。如int。</li><li>==:如果判断引用类型,判断的是地址是否相等,即判断是不是同一个对象。</li><li>equals:是object类中的方法,只能判断引用类型。</li><li>默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。比如Integer(已重写),String。</li></ol>
hashCode方法<br><ol><li>提高具有哈希结构的容器的效率。</li><li>两个引用,如果指向是同一个对象,哈希值肯定是一样的。</li><li>两个引用,如果指向的是不同对象,则哈希值是不一样的。</li><li>哈希值主要是根据地址号来的,但是不能完全将哈希值等价于地址。</li></ol>
toString方法<br>基本介绍 默认返回:全类名+@+哈希值的十六进制(查看object类的toString方法)。<br>子类往往重写toString方法,用于返回对象的属相信息。<br><font color="#d32f2f">当直接输出一个对象时,toString方法会被默认的调用。</font>
finalize方法<br><ol><li>当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作。</li><li>什么时候被回收:当某个对象没有任何引用时,则jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法。</li><li>垃圾回收机制的调用,是由系统来决定(即它有自己的GC算法),也可以通过System.gc()主动出发垃圾回收机制。</li></ol>
debug
断点调试介绍:在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后可以一步步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。进行分析从而找到这个bug.
提示:<font color="#ff0000">在断点调试过程中,是运行状态,是以对象的运行类型来执行的。</font><br>断点调试能帮助查看java底层源代码的执行过程,提高java水平。
常用快捷键:<br><ol><li>F7跳入,跳入方法内</li><li>F8跳过,逐行执行代码 </li><li>shift+F8跳出方法</li><li>F9resume,执行到下一个断点<br>将光标放到某个变量上,可以看到最新的数据。<br>断点可以在debug过程中,动态的下断点。</li></ol>
进入jdk源码的方法
面向对象编程(高级)
类变量
static变量保存:<br><ol><li>在class实例的尾部。class对象在堆中。所以static变量在堆中。</li><li>jdk7以上版本,静态域存储于定义类型的class对象中,class对象如同堆中其他对象一样,<br>存在于gc堆中。(有说法静态域在方法区中..jdk版本有关系)</li></ol>
共识:<br><ol><li>static变量是同一类所有对象共享。</li><li>static类变量,在类加载的时候就生成了。</li></ol>
什么是类变量<br>类变量也叫静态变量【静态属性】,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量。
如何定义类变量<br>定义语法: 访问修饰符 static 数据类型 变量名;<br>访问修饰符和static位置可以互换。
如何访问类变量<br>类名.类变量名(推荐)<br>对象名.类变量名<br>注意:静态变量的访问修饰符权限和普通一样。
使用注意事项和细节讨论<br>
什么时候需要用到类变量<br>当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量);
类变量与实例变量【普通属性】区别<br>类变量是该类的所有对象共享的,而实例变量是每个对象独享的。<br><br>
<font color="#ff0000">加上static称为类变量【静态变量】,没有就是实例变量【普通变量,非静态变量】</font>
类变量可以通过类名.类变量名(推荐)或者对象名.类变量名来访问(满足访问权限和范围)
实例变量不能通过 类名.类变量名方式访问。
类变量在类加载时就初始化了,也就是说,即使没有创建对象,只要类加载了,就可以使用类变量了。
类变量的声明周期是随类的加载开始,随着类消亡而销毁。
类方法
类方法基本介绍<br>类方法也叫静态方法。<br>访问修饰符 static 数据返回类型 方法名(){}推荐<br>static 访问修饰符 数据返回类型 方法名(){}<br>
类方法调用:<br>类名.类方法名或者对象名.类方法名(满足修饰符访问权限)
使用场景:<br><font color="#ff0000">当方法中不涉及到任何和对象相关的成员,则可以讲方法设计成静态方法,提高开发效率。</font><br>常见:工具类中的方法。
注意事项和细节讨论<br><ol><li>类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法去:类方法中无this的参数 普通方法中隐含着this的参数。</li><li>类方法可以通过类名调用,也可以通过对象名调用。</li><li>普通方法和对象有关,需要通过对象名调用,不能通过类名调用。</li><li>类方法中不允许使用和对象有关的关键字,比如this和super。普通方法都可以。</li><li>类方法【静态方法】中只能访问静态变量或静态方法。</li><li>普通成员方法,既可以访问普通变量(方法)也可以访问静态变量(方法)。</li></ol>
main方法
深入理解main方法<br><ol><li>main方法是虚拟机调用。</li><li>java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public。</li><li>java虚拟机在运行main方法时不必创建对象,所以该方法必须是static。</li><li>该方法接收string类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数。</li><li>java hello第一个参数,第二个参数 (在main方法中,打印args,可打印参数值。hello是类名)</li></ol>
特别提示:<br>在main()方法中,我们可以直接调用main方法所在类的静态方法或静态属性。<br>但是不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,<br>才能通过这个对象去访问类中的非静态成员。
代码块
基本介绍<br>代码化块又称为初始化块,属于类中的成员(即类的一部分),类似于方法,将逻辑语句封装在方法体中,通过{}包围起来,但是和方法不同,没有方法名,没有返回,没有参数,只有方法体,而且不用通过对象或类显示调用,而是加载类时,或创建对象时隐式调用。
基本语法[修饰符]{代码};<br><ol><li>修饰符,可选,写或不写,写的话,只能写static。</li><li>代码块分为两类,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块。</li><li>逻辑语句可以为任意逻辑语句(输入,输出,方法调用,循环,判断等)</li><li>;号可以写上,也可以省略。</li></ol>
注意事项和细节讨论
注意事项和细节讨论<br><ol><li>static代码块也叫静态代码块,作用就是对类进行初始化,而且它随着类的加载而执行,并且只会执行一次。</li><li>类什么时候被加载? 1、创建对象实例。 2、创建子类对象实例。 3、使用类的静态成员(静态属性、静态方法)时。</li><li>普通的代码块,在创建对象实例时,会被隐式的调用,被创建一次,调用一次。如果是使用类的静态成员时,普通代码块并不会执行。</li></ol>
4.创建一个对象时,在一个类中调用顺序是:<br><ol><li>调用静态代码块和静态属性初始化(注意:静态代码块和静态属性初始化调用的优先级一样,如果有多个静态代码块和多个静态属性初始化,则按它们定义的顺序调用)。</li><li>调用普通代码块和普通属性的初始化(注意:普通代码块和普通属性初始化调用的优先级一样,如果有多个普通代码块和多个普通属性初始化,则按它们定义的顺序调用)。</li><li>调用构造方法。</li></ol>
5.构造方法(构造器)的最前面其实隐含了super()和调用普通代码块。静态相关的代码块,属性初始化,在类加载时,就执行完毕,因此是优先于构造器和普通代码块执行的。
6.创建一个子类时,它们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如:<br><ol><li>父类的静态代码块和静态属性(优先级一样,按定义顺序执行)。</li><li>子类的静态代码块和静态属性(优先级一样,按定义顺序执行)。</li><li>父类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)。</li><li>父类的构造方法。</li><li>子类的普通代码块和普通属性初始化(优先级一样,按定义顺序执行)。</li><li>子类的构造方法。<br></li></ol>
7.静态代码块只能调用静态成员(静态属性和静态方法),普通代码块可以调用任意成员。
static在设计模式中应用
什么是设计模式?<br><ol><li>静态方法和属性的经典使用。</li><li>设计模式是在大量的时间中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式。</li></ol>
什么是单列模式(单个的实例)<br>所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。<br>单例模式有两种方式:1)饿汉式 2)懒汉式
单例模式应用实例<br><ol><li>构造器私有化=>防止直接new创建。</li><li>类的内部创建对象。</li><li>向外暴露一个静态的公共方法。getInstance();</li></ol>
饿汉式vs懒汉式<br><ol><li><font color="#ff0000">二者最主要的区别在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建。</font></li><li>饿汉式不存在线程安全问题,懒汉式存在线程安全问题。</li><li>饿汉式存在浪费资源的可能。因为如果程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,懒汉式是使用时才创建,就不存在这个问题。</li><li>应用场景:javaSE标准类中,java.lang.Runtime就是经典的单例模式。</li></ol>
final关键字
final可以修饰类、属性、方法和局部变量;
在某些情况下,程序员可能有以下需求,就会使用final:<br><ol><li>当不希望类被继承时,可以用final修饰。</li><li>当不希望父类的某个方法被子类覆盖【重写】时,可以用final关键字修饰。</li><li>当不希望类的某个属性的值被修改,可以用final修饰。public final double TAX_RATE=0.08</li><li>当不希望某个局部变量被修改时,可以使用final修饰。final double TAX_RATE=0.08</li></ol>
注意事项和细节讨论<br><ol><li>final修饰的属性又叫常量,一般用xx_xx_xx命令。</li><li>final修饰的属性在定义时,必须赋初始值,并且以后不能再修改,赋值可以在:定义时;在构造器中;在代码块中,三个位置。</li><li>如果final修饰的属性是静态的,则初始化的位置只能是定义时;在静态代码块中;不能在构造器中。</li><li>final类不能继承,但是可以实例化对象。</li><li>如果类不是final类,但是含有final方法,则该方法虽然不能重写,但是可以被继承。</li><li>一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法。</li><li>final不能修饰构造方法(即构造器)。</li><li>final和static往往搭配使用,效率更高,底层编译器做了优化处理。搭配使用,不会进行类加载。</li><li>包装类,String都是final类。</li></ol>
抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法(用abstract关键字修饰该方法),那么这个类就是抽象类(用abstract来修饰该类)。
抽象类的介绍<br><ol><li>用abstract关键字修饰一个类,这个类叫做抽象类。</li><li>用abstract关键字修饰一个方法,这个方法叫做抽象方法。</li><li>抽象的价值更多作用在于设计,是设计者设计好后,让子类继承并实现抽象类。</li><li>抽象类,在框架和设计模式中使用较多。</li><li>抽象类可以有任意成员(抽象类本质还是类),比如非抽象方法、构造器、静态属性等等。</li><li>抽象方法不能有主体,即不能实现。</li><li>如果一个类继承了抽象方法,则它必须实现抽象类的所有抽象方法,除非它自己也声明为abstract类。</li><li>抽象方法不能使用private final static修饰,因为这些关键字都是和重写相违背的。</li></ol>
抽象类的应用:模板设计模式
集合
集合框架体系
collection
list
arrayList
vector
linkedList
set
hashset
linkedHashSet
treeSet
map
hashMap
LinkedHashMap
hashTable
properties
treeMap
经典接口
单列接口
collection
遍历方式
iterator
游标<br><ul><li>hasNext()判断集合中下一位置是否有值。</li><li>next()返回游标下一位置的值,并将游标下移。</li></ul>
注意点:如果使用迭代器,对集合进行遍历之后,此时游标在集合的最下方。想再次遍历集合,需要给游标重新赋值,重新获取集合迭代器即可。
增强for
简易版的迭代器,它的底层就是调用的迭代器。
注意点:可用于集合,也可用于数组。
List
遍历方式
iterator
增强for
普通for
排序
使用冒泡结合集合中设置元素的方法完成。
ArrayList
注意事项
可以放null值,可以放多个null值。
底层实现为数组,可从源码中获得。
基本与vector相同,线程不安全的集合,效率高,但是不建议在多线程中使用。
底层结构与源码分析
arrayList中维护了一个object类型的数组elementData。<br>transient object【】elementData; // transient表示瞬间,短暂的<br>表示该属性不会被序列化。
当创建arrayList对象时<br><ol><li>如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。</li><li>如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。</li></ol>
扩容使用的是Array.copyOf();这样可以保留原来的数据,在保留原来数据的基础上扩容。
注意:idea有可能会打断点无法进入。需要设置:如图。
vector
注意事项
vector底层也是一个对象数组,protected Object[] elementData;
vector是线程同步的,即线程安全的,vector类的操作方法带有synchronized修饰。<br>但注意并不是需要线程安全,就一定要使用vector,如果这个集合,仅在一个线程<br>运行,那么完全可以使用arrayList,这样效率更高。
底层结构与源码分析
vector底层结构与arrayList相同,都是数组。而底层的源码实现逻辑相同,只有细微区别:synchronized,扩容相关。
LinkedList
底层结构
linkedList底层维护了一个双向链表
linkedList中维护了两个属性first和last分别指向首节点和尾节点。
每个节点(Node)对象,里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表。
基于底层的结构,linkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高(没有扩容处理)。
源码分析
注意:因为LinkedList是双向链表,进行集合操作时,其实操作的是pre和next。
与arrayList的应用场景对比
LinkedList改查的时候,是从头开始。
set
<ul><li>无序,没有索引,但是每次取出的时候,顺序是固定的,它的底层是有一定算法的。</li><li><span style="font-size:inherit;">不允许元素重复,允许存在null,但是只能存在一个。</span></li></ul>
遍历方式:<br><ul><li>迭代器。</li><li>增强for。</li></ul>
hashSet
hashSet的底层其实是hashMap,它在源码里直接调用了hashMap(数组+链表+红黑树)。<br>为什么不直接使用数组,而是加上了链表。。 为了提高效率。
添加元素的底层机制
hashSet底层是HashMap
添加一个元素时,先得到hash值(不是hashcode值,hashcode值经过一个算法得到的结果值)-》会转成索引值。
找到存储数据表table,看这个索引为止是否已经存放有元素<br>如果没有,直接加入。<br>如果有,调用equals(可自行重写定义)比较,如果相同,就放弃添加,如果不同,则添加到最后。
扩容与树化转成红黑树的机制
hashSet底层是hashMap,第一次添加时,table数组扩容到16,临界值(threshold)是 16×加载因子(loadFactor)是0.75=12
如果table数组使用到了临界值12,就会扩容到16*2=32,新的临界值就是32*0.75=24以此类推
<font color="#ff0000">在java8中,如果一条链表的元素个数到达TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制。</font><br><ul><li>这里的链表元素计算个数时,是从节点1开始算,也就是说第一个集合中的第一个值是算到数组中的。此时元素个数到达8就会进行扩容,或者树化。如果按照集合中的元素算,是集合中的元素个数达到9,才开始数组扩容或树化。</li><li>如果一个集合中只有一个位置上有元素,最多可以放10个,16->32->64,两次扩容就达到的树化标准(Node->TreeNode)。</li></ul>
注意事项:临界值12,不是说table中的数据达到12,而是说node的总值达到12.比如索引1上有7个元素,索引2上有6个元素,其他都为null,那么此时也会进行扩容。
linkedHashSett
<ol><li>linkedHashSet是HashSet的子类;</li><li>linkedHashSet底层是一个linkedHashMap,底层维护了一个数组+<font color="#ff0000">双向链表</font>。</li><li>linkedHashSet根据元素的hashCode值来决定元素的存储位置,同时使用链表维护元素的次序(使用entry(不是node)中的before和after将插入的相邻元素连接起来),这使得元素看起来是以插入顺序保存的。</li></ol>
底层机制:<br><ol><li>在linkedHashSet中维护了一个hash表(数组table)和双向链表(linkedHashSet有head和tail相当于hashset的first和end)。</li><li>每个节点都有before和after属性,这样可以形成双向链表。(注意也可以说成pre和next)</li><li>在添加一个元素时,先求hash值,在求索引,确定该元素在hash表中的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加【原则和hashset一样】)tail.next=newELement;// 简单指定 newElement.pre=tail; tail=newElement;<br>通过以上,我们遍历linkedHashSet也能确保插入顺序和遍历顺序一致。</li></ol>
treeSet
基本介绍:有序的不重复的集合【底层个 使用了treeMap】<br><font color="#ff0000"></font>当我们想有序排列时,可在构造方法中传入一个比较器(匿名内部类)。在匿名内部类中制定排序规则,需要注意的是,如果两个元素,按照制定的排序规则,比较为相同时,会不再添加该元素。比如,当使用字符串的长度进行排序,那么元素:a,ab,ac。3个元素,ac会加不进去。
当我们使用无参构造方法创建treeSet时。<br>没有传入比较器时,如果集合中的对象实现类了Comparator接口,那么在调用比较器,进行排序时是没有问题的,如String对象。如果是定义的对象如Student。需要实现Comparator接口,否则,会报错。classCastExeption
双列接口
map
<ol><li>map与collection并列存在。用于保存具有映射关系的数据:key-value</li><li>map中的key和value可以是任何引用类型的数据,会封装到hashMap$Node对象中</li><li>map中的key不允许重复,原因和hashSet一样。</li><li>map中的value可以重复。</li><li>map中的key可以为null,value也可以为null,key的null只能有一个,value的key可以有多个。</li><li>常用String类做为map的key,但是任何引用类型的数据都可以作为key。</li><li>key和value之间存在单向一对一关系,即通过指定key总能找到对应的value。</li><li>map存放的数据,一对k-v是存放在node中的,node实现了map.entry<k,v>接口。为了方便遍历,增加了Set set=map.keyset;Collection values=map.getValues(); 其实都是指向了node中k,v,并不是底层实现,存在了set和values中。可以通过set和values中对象的地址与node中的对象地址对比,来查看获得。</li></ol>
遍历
keyset+map.get(key)
迭代器
增强for
values
迭代器
增强for
entrySet
迭代器
增强for
hashMap
<span style="font-size:inherit;">概要:</span><br><ul><li><span style="font-size:inherit;">hashMap是map接口使用频率最高的实现类。</span></li><li><span style="font-size:inherit;">hashMap是以k-v对的方式来存储数据(hashMap$node类型)</span></li><li><span style="font-size:inherit;"><font color="#ff0000">key不能重复,但是值可以重复,允许使用null键和null值,如果添加相同的key,则会覆盖原来的k-v,等同于修改。(key不会被替换,value会被替换),阅读源码可得。</font></span></li><li><span style="font-size:inherit;">与hashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的。(jdk8的hashMap底层 数组+链表+红黑树)</span></li><li><span style="font-size:inherit;">hashMap是线程不安全,没有实现同步互斥,方法上没有synchronized关键字。</span></li></ul>
hashMap底层机制-扩容【与hashset相同,其实hashset底层原理就是hashmap】<br><ol><li>hashMap底层维护了Node类型的数组table,默认为null。</li><li>当创建对象时,将加载因子(loadfactor)初始化为0.75。</li><li>当添加key-value,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key和准备加入的key是否相等,如果相等,则直接替换value;如果不相等需要判断是树结构还是链表结构,做出相应处理。如果添加时发现容量不够,则需要扩容。</li><li>第一次添加,则需要扩容table容量为16,临界值(threshold)为12(16*0.75)。</li><li>以后再扩容,则需要扩容table容量为原来的2倍(32),临界值为原来的2倍,即24,以此类推。</li><li>在java8中,如果一条链表的元素个数超过TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树)。</li></ol>
注意点:当table中达到临界值(table长度×0.75)会触发扩容。还有一种情况是,当table中在一个索引位置上,也就是一个链表上,达到8个之后且table的长度不够64,此时不会去树化,而是先去扩容,直到table的长度达到64。
hashTable
基本介绍:<br><ul><li>hashTable的键和值都不能为null(底层会判断,报空指针异常)。</li><li>hashTable的使用方法基本上和hashMap一样。</li><li>hashTable的线程安全的(synchronized),hashMap是线程不安全的。</li><li>hashTable的初始化,集合长度为11,扩容机制为11*2+1,再次扩容为23,负载因子为0.75。</li></ul>
properties
基本介绍:<br><ul><li>properties类继承自hashTable类并且实现了map接口,也是使用一种键值对的形式来保存数据。</li><li>它的使用特点和hashTable类似。</li><li>properties还可以用于从xxx.properties文件中,加载数据到properties类对象,并进行读取和修改。</li></ul>注意:xxx.properties文件通常作为配置文件,这个知识点在io流举例。
treeMap
基本介绍:有序的不重复的集合<br><span style="font-size:inherit;">当我们想有序排列时,可在构造方法中传入一个比较器(匿名内部类)。在匿名内部类中制定排序规则,需要注意的是,如果两个元素,按照制定的排序规则,比较为相同时,会不再添加该元素。比如,当使用字符串的长度进行排序,那么元素:a,ab,ac。3个元素,ac会加不进去。</span><br>
当我们使用无参构造方法创建treeSet时。<br>没有传入比较器时,如果集合中的对象实现类了Comparator接口,那么在调用比较器,进行排序时是没有问题的,如String对象。如果是定义的对象如Student。需要实现Comparator接口,否则,会报错。classCastExeption
集合常用场景
主要取决于业务操作特点,然后根据集合实现类特性进行选择。<br>1)先判断存储的类型(一组对象【单列】或一组键值对【双列】)<br>2)一组对象:collection接口<br> 允许重复:list<br> 增删多:linkedList【底层维护了一个双向链表】<br> 改查多:arrayList【底层维护object类型的可变数组】<br> 不允许重复:set<br> 无序:hashSet【底层个是hashMap,维护了一个哈希表即(数组+链表+红黑树)】<br> 排序:treeSet<br> 插入和取出顺序一致,linkedHashSet,维护数组+双向链表<br>3)一组键值对:map<br> 键无序:hashMap【底层jdk7:数组+链表jdk8:数组+链表+红黑树】<br> 键排序:treeMap<br> 插入和取出顺序一致:LinkedHashMap,维护数组+双向链表<br> 读取文件:properties<br>
collections
排序操作:<br><ul><li>reverse(list):反转list中元素的顺序</li><li>shuffle(list):对list集合元素进行随机排序</li><li>sort(list):根据元素的自然顺序对指定list集合元素按升序排序</li><li>sort(list,Comparator):根据指定的Comparator产生过的顺序对list集合元素进行排序</li><li>swap(list,int i,int j):将指定list集合中的i处元素和j处元素进行交换</li></ul>
查询、替换操作:<br><ul><li>object max(collection):根据元素的自然顺序,返回给定集合中的最大元素</li><li>object max(collection,Comparator):根据Comparator指定的顺序,返回给定集合中的最大元素</li><li>object min(collection)</li><li>object min(collection,Comparator)</li><li>int frequency(collection,object)返回指定集合中指定元素的出现次数</li><li>void copy(List dest,List src):将src中的内容复制到dest中</li><li>boolean replaceAll(List list,Object oldvalue,Object newValue):使用新值替换List对象的所有旧值</li></ul>
Java概述
Java历史
95年发布第一个版本
java之父-詹姆斯·高斯林 (James Gosling)
现在公司使用更多的版本:java8、java11
所属公司:之前所属sun公司,后被甲骨文收购。
Java技术体系平台
JavaSE(Java Standard Edition)标准版<br>支持面向桌面级应用(如Windows下的应用程序)的java平台,提供了完整的Java核心API,此版本以前成为J2SE
JavaEE(Java Enterprise Edition)企业版<br>是为开发企业环境下的应用程序提供的一套解决方案。该技术体系中包含的技术如:Servlet、Jsp等,主要针对于Web应用程序开发。版本以前称为J2EE
JavaME(Java Micro Edition)小型版<br>支持Java程序运行在移动终端(手机、PDA)上的平台,对JavaAPI有所精简,并加入了针对移动终端的支持,此版本以前成为J2ME<br>曾火过一段时间,后期受安卓影响较大。
Java的特性
Java是面向对象的(oop)
Java语言是健壮的。Java的强类型机制、异常处理、垃圾的自动收集等是Java程序健壮性的重要保证。
Java语言是跨平台性的。【即一个编译好的.class文件可以在多个系统下运行,这种特性称为跨平台】
Java语言是解释型的【了解】<br>解释型语言:JavaScript、php、java 编译型语言:c、c++<br>区别:解释型语言,编译后的代码,不能直接被机器执行,需要解释器来执行,编译型语言,编译后的代码,可以直接被机器执行。
Java常用工具
nodepad++、editplus、sublime、idea、eclipse
JDK
Java运行机制及运行过程<br>Java语言的特点:跨平台性 <br>因为有了JVM,同一个Java程序在三个不同的操作系统(windows、linux、mac)中都可以执行(针对三种系统,有3个版本Jvm,Jvm负责对class文件进行解释执行),这样就实现了Java程序的跨平台性。
Java虚拟机基本介绍<br>Jvm是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在JDK中。<br>对于不同的平台,有不同的虚拟机。<br>Java虚拟机机制屏蔽了底层运行平台的差别,实现了"一次编译,到处运行"。
JDK、JRE基本介绍<br><ul><li>JDK的全称(Java Development Kit Java开发工具包),JDK=JRE+Java的开发工具包【java、javac、Javadoc、javap等】。JDK是提供给Java开发人员使用的,其中包含了java的开发工具,也包含了JRE。</li><li>JRE(Java Runtime Environment Java运行环境),JRE=JVM+Java的核心类库【类】。包括Java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等,如果想要运行一个开发好的Java程序,计算机只需要安装JRE即可。</li></ul>
安装、配置
用户变量:电脑当前用户生效<br>系统变量:所有用户生效
快速入门
运行<br><ul><li>有了可执行的java程序(Hello.class字节码文件)</li><li>通过运行工具java.exe对字节码文件进行执行,本质就是.class装载到jvm机执行。(注意:如果Hello.java源文件需要重新编译,生成新的class文件后,在进行执行,才能生效)。</li></ul>
注意细节:<br><ul><li>一个源文件中最多只有一个public类,但是其他类的个数不限。</li><li>编译后,每一个类对应一个class文件。</li><li>源文件名必须与public的类名对应。</li></ul>
注释
可读性,为己为人
单行注释//
多行注释/**/<br>
注释中的内容不会被Jvm执行
<font color="#ff0000">多行注释中不允许嵌套多行注释。</font>
文本注释
注释内容可以被jdk提供的工具javadoc所解析,生成一套以网页文件形式体现的该程序的说明文档,一般写在类。<br>基本格式<br>/** <br>@author<br>*/<br>生成对应的文档注释:javadoc -d 文件夹名 -xx -yy Demo3.java<br>举例:javadoc -d D:\\temp -author Demo3.java 生成一个文档注释,位置在d盘下的temp文件中,生成的标签有author,其他标签不生成,对应的java类为Demo3。
代码规范(基础版)
类、方法的注释要以javadoc的方式来写。
非javadoc的注释,一般是给代码的维护者看的,着重告诉读者为什么这样写,如何修改,注意什么问题,一般用单行、多行注释。
注释代码的格式:使用tab右移,使用shift+tab左移。
运算符和=两边习惯各加一个空格。
源文件使用utf-8编码,如果是dos窗口javac、java命令操作文件时,为了能阅读,它的编码是gbk。
代码行宽度不要超过80字符。idea中有个右竖线,按照那个就可以。
代码编写次行风格{在方法名同行(推荐)和行尾风格{另起一行。
dos命令
dos介绍:<br>disk operating system磁盘操作系统。
常用dos命令<br><ul><li>查看当前目录有什么: dir</li><li>切换到其他盘: cd</li><li>切换到当前盘:cd 绝对路径,cd 相对路径</li><li>切换到上一级:cd ..</li><li>切换到根目录:cd \<br>查看目录下的所有文件夹:tree 目录<br>清屏:cls<br>退出:exit</li></ul>
了解其他命令,主要操作都在linux系统中,而且命令会发生变化,此处了解即可。<br><ul><li>md【创建目录】rd【删除目录】copy【拷贝文件】copy+文件名+拷贝到的目录以及新文件名 del【删除文件】move【剪切】</li><li>echo【输入内容到文件】echo ok->hello.txt 创建一个hello.txt内容为ok</li><li>type【控内容到文件】type nul->hello.txt 创建一个hello.txt内容为空</li></ul>
相对路径-绝对路径
如图举例: ..\ 上一级目录
变量
变量介绍
为什么需要变量?<br>不论是使用那种高级程序语言编写程序,变量都是其程序的基本组成单位。
概念<br>变量相当于内存中一个数据存储空间的表示,可以把变量看做一个房间的门牌号,通过门牌号可以找到房间,而通过变量名可以访问到变量值。<br>变量的使用步骤<br>声明变量 int a; 赋值 a=4;或者int a=4;<br>
注意事项:<br><ul><li>变量表示内存中的一个存储区域【不同的变量,类型不同,占用的空间大小不同】比如int4个字节,double就是8个字节。</li><li>该区域有自己的名称【变量名】和类型【数据类型】</li><li>变量必须先声明,后使用,即有顺序</li><li>该区域的数据可以在同一类型范围内不断变化。(重新赋值)</li><li>变量在同一个作用域内不能重名。</li><li>变量=变量名+值+数据类型,变量三要素。</li></ul>
+号
当左右两边都是数值型时,则做加法运算
当左右两边有一方为字符串,则做拼接运算
运算顺序,从左到右
数据类型
类型体系
基本数据类型
数值型
整数类型,存放整数(byte【1】,short【2】,int【4】,long【8】)
浮点(小数)类型(float【4】,double【8】)
字符型(char【2】)
布尔型(boolean【1】),存放true,false
引用数据类型(面向对象再讲)
类(class)
接口(interface)
数组【】
类型详讲
整型
整型基本介绍
整数类型的使用细节:<br>Java各整数类型有固定的范围和字段长度,不受固定OS【操作系统】的影响,以保证Java程序的可移植性。<br>Java的整型常量默认为int型,声明long型常量须后加‘l’或‘L’<br>Java程序中变量常声明为int型,除非不足以表示大数,才使用long<br>bit:计算机中最小存储单位。byte:计算机中基本存储单元1byte=8bit【二进制中详讲】。
浮点型
浮点型基本介绍
浮点型使用细节:<br><ul><li>与整型类似,Java浮点类型也有固定的范围和字段长度,不受具体os影响。【float4个字节double8个字节】</li><li>Java的浮点型常量(具体值)默认是double型,声明float型常量,须后加‘f’或‘F’</li><li>浮点型常量有两种表示形式:</li><li> 十进制数形式:如:5.12 512.0f .512(如果是零点几,零可以省略)</li><li> 科学计数法形式:如:5.12e2[5.12*10的2次方] 5.12E-2[5.12/10的2次方]</li><li>通常情况下,应该使用double型,因为它比float型更精确【小数保留的位数更多】。</li><li>浮点数使用陷阱:2.7与8.1/3比较。它俩直接用==为false. 那怎么判断处理,可以对它倆的差值取绝对值,在精度范围内判断,如果小于精度,为相。比如math.abs(a-b)<0.000001.</li></ul><br>
字符型
基本介绍<br>字符类型可以表示单个字符,字符类型是char,char是两个字节(可以存放汉字),多个字符用字符串string
使用细节<br><ul><li>字符常量是用单引号''括起来的单个字符</li><li>允许使用转义字符'\'来将其后的字符转变为特殊字符型常量,如char c='\n'; \n表示换行符。</li><li>char本质是一个整数,在输出时,是unicode码对应的字符。http://tool.chinaz.com/Tools/Unicode.aspx</li><li>可直接给char赋一个整数,然后输出时,会按照对应的unicode字符输出。38889 对应韩 </li><li>char类型是可以进行运算的,相当于一个整数,因为它都对应有unicode码。'a'+1 直接输出为字符int('a'+1)输出为整数。</li></ul>
本质探讨<br><ul><li>字符型 存储到计算机中,需要将字符对应的码值(整数)找出来,比如'a' 存储:'a'->码值97->二进制->存储;读取:二进制->97->'a'->显示</li><li>字符和码值的对应关系是通过字符编码表决定的(是规定好的)</li></ul>
字符编码表的介绍<br>ASCII(ASCII编码表 一个字节表示,一个128个字符)<br>unicode固定大小的编码,使用两个字节来表示字符,字母和汉字统一都占用两个字节,这样浪费空间。<br>utf-8大小可变的编码,字母使用1个字节,汉字使用3个字节<br>gbk可以表示汉字,而且范围广,字母使用1个字节,汉字2个字节<br>gb2312可以表示汉字,gb2312<gbk<br>big5码繁体中文,台湾,香港
ASCII码介绍:<br><ul><li>上世纪60年代,美国指定了一套字符编码(使用一个字节),对英语字符与二进制位之间的关系做了统一规定。这被称为ASCII码码。ASCII码码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的1位统一规定为0。【注意:此处表示,一个字节是可以表示256个字符的,ASCII码只用了128个字符】</li><li>缺点:不能表示所有字符。</li></ul>
unicode码介绍:<br><ul><li>unicode的好处:一种编码,将世界上所有的符号都纳入其中。每一个符号都给予一个独一无二的编码,使用unicode没有乱码的问题。</li><li>unicode的坏处:一个英文字母和一个汉字都占用2个字节,这对于存储空间来说是浪费。</li><li>2的16次方是65536,所以最多编码是65536个字符。</li><li>编码0-127的字符是与ASCII的编码一样。比如'a'->0x61 'a'->ox0061,都对应的是97。因此unicode码兼容ASCII码。</li></ul>
utf-8编码介绍(了解)<br><ul><li>utf-8是互联网上使用最广的一种unicode的实现方式。</li><li>utf-8是一种变长的编码方式。它可以使用1-6个字节表示一个符号,根据不同的符号而变化字节长度。</li><li>使用大小可变的编码,字母占用1个字节,汉字占用3个字节。</li></ul>
布尔型
基本介绍<br><ul><li>也叫boolean类型,只允许取true\false,无null</li><li>占1个字节</li><li>适于与逻辑运算,一般用于程序流程控制。if while do-while for</li></ul>
类型转换
自动类型转换
基本介绍:<br>当java程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数据类型,这个就是自动类型转换。<br>char->int->long->float->double<br>byte->short->int->long->float->double
自动类型转换注意和细节:<br>有多种类型的数据混合运算是,系统首先自动将所有数据转换成容量最大的那种数据类型,在进行计算。<br>当我们把精度(容量)大的数据类型赋值给精度(容量)小的数据会报错,反之就会进行自动类型转换。<br><font color="#ff0000">(byte,short)和char之间不会相互自动转化(规定)。注意byte a =10;short b=10;是可以的,计算机会查看给byte的赋值是否在它的取值范围内,如果在,可以。如果不在,会报错。范围-128~127。另外一种情况 int x=10; byte a=x;这种情况是不可以的,这种情况,x已经是int类型的数据了。<br>byte、short、char他们三者可以计算,在计算时会将数据类型提升为int。<br>boolean不参与转换。</font><br><font color="#ff0000">自动提升原则:表达式结果的类型自动提升为操作数中最大的类型。<br>char a=‘男’;char b=‘女’;System.out.println(a+b); //此时输出的是两个码值的相加,是个数字,不是字符。</font>
强制类型转换
基本介绍:<br>自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换符(),但可能造成精度降低或溢出,格外要注意。(int)1.9 是精度降低,得到了1;(byte)2000,是溢出,得到的是-48。
细节说明:<br>只针对最近的操作数有效,往往会使用小括号提升优先级(int)(10*3.5)<br>char类型可以保存int的变量值,但不能保存int的变量,需要强转【这个正常呀,注意一下】。
基本数据类型和String类型的转换
基本介绍:<br>在程序开发中,我们会经常将两者互相转换。
基本类型--》String:将基本类型的值+""。<br>
String--》基本类型:通过基本类型的包装类调用parseXx方法即可。<br>Integer.parseInt("123");<br>Double.parseDouble("123.1");<br>依次有byte、short、long、float、boolean。<br>字符特殊一些 Char.charAt(0);将字符串第一个位置的元素转为字符。
注意事项:<br>将String转换为基本类型,注意String的值,“123”可以,“hello”自然就不行,会抛出异常。
运算符
运算符体系
算术运算符
赋值运算符
关系运算符【比较运算符】
逻辑运算符
位运算符【需要二进制基础】
三元运算符
运算符详讲
算术运算符
一览图
注意细节:<br><ol><li>%取模,看一个公式:a%b=a-a/b*b;举例:-10%3=-1; 10%-3=1; -10%-3=-1;</li><li>i++,++i 自增效果一样。运算时:前者取自增前值,后者取自增后值。</li></ol>
关系运算符
一览图<br>注意:运算符"=="不要误写成"="
逻辑运算符
一览图
&&短路与与&逻辑与的使用区别<br><ul><li>&&短路与:如果第一个条件为false,则第二个条件不会判断,最终结果为false,效率高(开发中使用&&)。</li><li>&逻辑与:不管第一个条件是否为false,第二个条件都要判断,效率低。</li></ul>
||短路或与逻辑或|类比'与'即可。
逻辑异或:两个一样为false,两个不一样为true.
赋值运算符
赋值运算符的分类:<br><ul><li>基本赋值运算符:=</li><li>复合赋值运算符:+= -= *= /= %=等。</li></ul>
赋值运算符特点:<br>从右往左:int num=a+b+c;<br>左边只能是变量,右边可以是变量、表达式、常量值。<br><font color="#ff0000">复合赋值运算符a+=3;等价于a=a+3; 且具有强转效果(byte类型+=3;可以)</font>
三元运算符
基本语法:条件表达式?表达式1:表达式2;<br>运算规则:条件表达式为true,结果为表达式1,反之为表达式2。
运算符的优先级
一览表<br>运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。<br>如上图,上一行的运算符总优于下一行。<br>使用时,用括号比较实用。
<ol><li>(),{}等。</li><li>单目运算符,++,--。</li><li>算术运算符</li><li>位移运算符</li><li>比较运算符</li><li>逻辑运算符</li><li>三元运算符</li><li>赋值运算符</li></ol>
标识符
标识符概念:<br><ul><li>Java对各种变量、方法和类等命名时使用的字符序列称为标识符。</li><li>凡是自己可以起名字的地方都叫标识符。</li></ul>
标识符的命名规则(必须)<br><ul><li>26个英文字母大小写,0-9,_或者$组成。</li><li>数字不可以开头。</li><li>不可以使用关键字和保留字,但能包含关键字和保留字。</li><li>严格区分大小写,长度无限制。</li><li>标识符不能包含空格。</li></ul>
关键字一览表1)
关键字一览表2)
保留字一览表
命名规范(建议)<br>包名:多单词,都小写<br>类名、接口名:多单词首字母都大写,大驼峰。<br>变量名、方法名:小驼峰。<br>常量名:所有字母都大写,单词间下划线分隔。
键盘输入语句
用来接收用户输入的数据。<br><ul><li>导入该类所在包。</li><li>创建该类的对象。</li><li>调用里面的功能。</li></ul>
进制
进制介绍,对于整数有四种表示方式:<br><ol><li>二进制:0、1,满二进一,以0b或0B开头。</li><li>十进制:0-9,满十进一。</li><li>八进制:0-7,满八进一。以数字0开头表示。</li><li>十六进制:0-9以及A(10)-F(15),满十六进一。以0x或0X开头表示。此处A-F不区分大小写。</li></ol>
进制转换
其他进制转十进制:<br>规则:从最低位(右边)开始,将每个位上的数提取出来,乘以该进制的(位数-1)次方,然后求和。
十进制转其他进制:<br>规则:将该数不断除以该进制,直到商为0为知,然后将每部得到的余数倒过来,就是对应的该进制数。如34转为二进制数是0b100010.
二进制转换成八进制<br>规则:从低位开始,将二进制每3位一组,转成对应的八进制数即可。
二进制转换成十六进制<br>规则:从低位开始,将二进制每4位一组,转成对应的十六进制数即可。
八进制转换成二进制:<br>规则:将八进制数每1位,转换成对应的一个3位的二进制数即可。
十六进制转换成二进制:<br>规则:将十六进制数每1位,转换成对应的一个4位的二进制数即可。
位运算(了解)
位运算的思考:>> <<等等。
二进制在运算的中的说明:<br><ol><li>二进制是逢2进位的进位制,0、1是基本算符。</li><li>现代的电子计算机技术全部采用的是二进制,因为它只使用0、1两个数字字符,非常简单方便,易于用电子方式实现。计算机内部处理的信息,都是采用二进制数来表示的。二进制(binary)数用0和1两个数字及其组合来表示任何数。进位规则是“逢2进1”,数字1在不同的位上表示不同的值,按从右至左的次序,这个值以二倍递增。</li></ol>
原码、反码、补码运算规则<br>对于有符号的而言:<br><ol><li>二进制的最高位是符号位:0表示正数,1表示负数。</li><li>正数的原码,反码,补码都一样。</li><li>负数的反码=它的原码符号位不变,其他位取反(0-》1,1-》0)</li><li>负数的补码=它的反码+1,负数的反码=它的补码-1</li><li>0的反码、补码都是0</li><li>java没有无符号数,都是有符号的。</li><li>在计算机运算的时候,都是以补码的方式来运算的。</li><li>当我们看运算结果的时候,都看它的原码。</li></ol>
位运算符1)
案例1
案例2
案例3
位运算符2)
控制结构
顺序控制
分支控制
if、if-else、if-else if-else
单分支
双分支
多分支
嵌套分支(不超过3层,可读性不好)
switch
基本语法:<br><ul><li>switch关键字,表示switch分支。</li><li>表达式对应一个值。</li><li>case 常量1:当表达式的值等于常量1,就执行语句块1。</li><li>break:表示退出switch。</li><li>如果和case常量1匹配,就执行语句块1,如果不匹配,就继续匹配case常量2。此处需要注意case穿透,如果没有break,一直向下执行。</li><li>如果都没有匹配,则执行default。</li></ul>
注意事项和细节讨论<br>表达式数据类型,应和case后的常量类型一致,或者是可以自动转成可以相互比较的类型,比如输入的是字符,而常量是int。<br><font color="#ff0000">switch(表达式)中表达式的返回值必须是:byte short int char enum String</font><br>case 子句中的值必须是常量,不能是变量,可以是表达式。<br>
swith与if的比较
如果判断的具体数值不多,而且符合byte short 等6种类型。虽然两个都可以使用,建议使用switch语句。
其他情况,如区间判断,boolean类型判断,使用if,if的使用范围更广。
循环控制
for
基本语法:<br>for(循环变量初始化;循环条件;循环变量迭代){<br>循环操作(语句);<br>}
编程思想:<br><ul><li>化繁为简</li><li>先死后活</li></ul>
while
基本语法,while循环也有四要素只是位置不一样:<br>循环变量初始化;<br>while(循环条件){<br>循环体(语句);<br>循环变量迭代;<br>}
dowhile
基本语法:<br>循环变量初始化;<br>do{<br>循环体(语句);<br>循环变量迭代;<br>}while(循环条件);<br>先执行,再判断,也就是说,一定会执行一次。
多重循环
将一个循环放到另一个循环体内,也就是嵌套循环。一般两层,最多不超过3层,可读性差。
break
break语句出现在多层嵌套的语句块中,可以通过标签指明要终止的是哪一层的语句快。<br><ul><li>break 语句可以指定退出那一层,不指定时为最近的循环体。</li><li>循环语句。上的label1: 为标签名。</li><li>实际开发中,尽量不适用标签。</li></ul>
continue
continue语句使用细节与break一致,区别在于continue语句用于结束本次循环,继续执行下一次循环。
return
return使用字方法,表示跳出所在的方法(如果方法是main方法,会退出程序)。
数组、排序、查找
数组
数组的使用
使用方式1-动态初始化<br>数组的定义:数组类型【】数组名=new 数组类型【大小】;<br>数组的引用: 数组名【下标或者叫索引】
使用方式2-动态初始化<br>先声明,再创建。<br>数据这类型 数组名【】;<br>数组名=new 数据类型【大小】;<br>注意 数组名和【】,两个顺序谁在前都可以。
数组方式3-静态初始化<br>数据类型 数组名 【】={元素值,元素..}
数组使用注意事项和细节<br><ul><li>数组中的元素可以是任何数据类型,但是不能混用,是多个相同的数据类型。</li><li>数组创建后,如果只定义大小,没有赋值,此时数组是有默认值的。int 0 ,short 0,byte 0, long 0, float 0.0, double 0.0, char \u0000, boolean false ,String null。</li><li>数组的下标是从0开始的。</li><li>数组的使用步骤:1声明数组并开辟空间2给数组各个元素赋值3使用数组</li><li>数组属于引用类型,数组型数据是对象(object)</li></ul>
数组的赋值机制<br>基本数据类型赋值,值传递【值拷贝】<br>数组类型赋值,引用传递(赋的值是地址)
值传递与引用传递的区别
数组的翻转
数组的扩容、缩减
原理:数组的扩容等,都是复制原有数组,创建新的数组,效率是很低的。
注意点:创建新的数组之后,之前的数组,在堆中没有指引之后,会被Jvm回收。
排序
排序的分类
内部排序:<br>指将需要处理的所有数据都加载到内部存储器中进行排序。包括(交换式排序法、选择式排序法、插入式排序法)
外部排序法:<br>数据量过大,无法全部加载到内存中,需要借助外部存储进行排序。包括(合并排序法、直接合并排序法)
经典排序
冒泡排序法
基本思想:<br>通过对待排序序列从后向前(从下标较大的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就像水底下的气泡一样向上冒。
查找
顺序查找(挨个,从头到尾比较)
二分法查找(算法时讲解)
二维数组
<ol><li>定义形式:int [][]</li><li>理解:原来的一维数组的每个元素也是一维数组时,就构成了二维数组,在结构上相当于嵌套。</li><li>获取值:arr[i],arr[i][j]</li></ol>
二维数组的使用
使用方式1:动态初始化<br>语法:类型【】【】数组名=new 类型【大小】【大小】。<br>举例:int arr [][]=new int[2][3].
使用方式2:动态初始化<br>先声明在开辟空间。<br>类型 数组名[][];<br>数组名= new 类型【大小】【大小】。
使用方式3:列数不确定。
使用方式4:静态初始化<br>类型 数组名[][]={{值1,值2..},{值1,值2..},{值1,值2..}}
二维数组的内存图
二维数组使用细节和注意事项
声明方式:<br>int [] [] y<br>int [] y []<br>int y [] []
二维数组实际上是由多个一维数组组成的,<font color="#ff0000">它的各个一维数组的长度可以相同,也可以不同。</font>
0 条评论
下一页
为你推荐
查看更多