Java基础
java中的int类型固定为32位
三个特殊的浮点值:正无穷大(`Double.POSITIVE_INFINITY`),负无穷大(`Double.NEGATIVE_INFINITY`)和NaN(`Double.NaN`)。
在java中,char类型用UTF-16编码描述一个代码单元.不建议在程序中使用char类型.
boolean类型的false和true并不能于整型相互转换.**0相当于false,1相当于true在java中并不适合**.
java,逐一声明每一个变量可以提高程序的可读性 `**int i = 0; int j = 0**`;
整数被0除将会产生一个异常,而浮点数被0除将会得到无穷大或者NaN
Java中关系运算符和boolean运算符包括: `**== != < > <= >= && || !**`
java中的位运算符包括: `**& | ^ ~ << >>**`
Java中的数值转换:
- Java中的数值计算会先将两个操作数转换为同一种类型(自动类型转换):
如果要将double转换成int,就需要使用强制类型转换.`double x = 0.0D; int y = (int)x**`;但是这种方式可能会丢失精度.如果试图将一个数值从一种类型强制转换为另一种类型,而又超出了目标类型的表示范围,结果就会被截断成一个完全不同的值.例如,(byte)300的实际值为44**
BigInteger类实现了任意精度的整数运算,BigDecimal实现了任意精度的浮点数运算.
枚举类型是变量取值的有限集合.
java没有内置的字符串类型.
使用**.equales()方法来判断**.不要使用==检测两个字符串是否相等.==比较的是字符串是否放在同一个位置.
如果虚拟机总是将相同的字符串共享,就可以使用`==`来检测字符串是否相等.但是实际上只有字符串常量是共享的.
- 空串”“是长度为0的字符串.
空串是一个Java对象,有自己的串长度(0)和内容(空)
使用 String.Format静态方法创建可以格式化的字符串,`String message = String.format("Hello,%s.Next year,you will be %d",name,age);`
使用 `**String.format("%1$s %2$tY/%2$tm/%2$td %2$tH:%2$tM:%2$tS","当前时间:",new Date())**`可以格式化当前时间
使用Arrays.sort()方法对数值型数组进行排序.
对象与类
实现封装的关键在于绝对不能让类中的方法直接访问其他类的实例域(成员变量).程序仅能通过对象的方法与对象数据进行交互.这是提高重用性和可靠性的关键.
要想使用OOP,一定要清楚对象的三个主要特性:
对象的行为:可以对对象施加哪些操作(方法). 对象的行为是用可调用的方法定义的.
对象的状态:当施加那些方法时,对象如何响应 每个对象都会保存描述当前特征的信息.这就是对象的状态.对象的状态可能会随着时间的改变而发生改变.但这种改变不会是自发的.必须通过调用方法实现(如果不经过方法调用就可以改变对象状态,只能说明封装性遭到了破坏).
对象的标识:怎样辨别具有相同行为与状态的不同对象. 作为一个类的实例,每个对象的标识永远是不同的,状态常常也存在着差异.
识别类的简单规则是在分析问题的过程中寻找名词,而方法则对应着动词.
类之间的常见关系有:
依赖(uses-a) 如果一个类的方法操作另一个类的对象,就说一个类依赖于另一个类(此种关系应该尽可能的降低到最低(低耦合)).
聚合(has-a) 如果一个类包含另一个类的对象.即类A的对象包含类B的对象.
继承(is-a) 如果类A扩展类B,类A不但包含从类B继承的方法,还会拥有一些额外的功能.
要想使用对象,就必须首先构造对象,并指定其初始状态.然后,对对象应用方法.
在Java中,任何对象变量的值都是对存储在另外一个地方的一个对象的引用.new 操作符的返回值也是一个引用.
局部变量不会自动地初始化为null,必须通过调用new或将他们设置为null进行初始化.
不要编写返回引用可变对象的getter方法.
如果需要返回一个可变对象的引用,应该首先对它进行克隆(clone).对象clone是指存放在另一个位置上的对象副本.(此处说的是返回一个可变对象的引用,而不是说返回对象本身;链式编程返回的是对象本身,即this)
用final修饰的成员变量,必须在构建对象时初始化.(定义时,构造方法中).
静态方法不能向对象实施操作.换句话说,静态方法没有隐式的参数.静态方法只能调用静态参数和静态方法.
当无法命令构造器或者想改变所构造的对象类型时,可以考虑使用工厂方法.
Java总是采用按值调用.方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容.
对于基本数据类型来说,原来的参数值是多少,经过方法处理后,原来的参数值还是多少.
double percent = 10; harry.raiseSalary(percent); System.out.print(percent); // 10
对于对象引用的参数来说,可以通过调用对象的方法来改变对象的状态.
总结Java中方法参数的使用情况
一个方法不能修改一个基本数据类型的参数(即数值型和布尔型)
一个方法可以改变一个对象参数的状态
一个方法不能让对象参数引用一个新的对象.
如果多个方法有相同的名字,不同的参数,便产生了重载.
成员变量与局部变量的不同点:
成员变量如果不在构造方法中进行初始化,那么则会自动的被赋予初始值.数值0,布尔值为false,对象引用为null.
而局部变量则必须明确得进行初始化.
对象由无参的构造方法创建时,对象中的成员变量会被设置为适当的默认值.
使用`this(...)`在构造方法中调用另一个构造方法.
类中的`{...}`代码块在构造类的对象时,就会被调用.`static {...}`静态代码块在ClassLoader的时候就会被调用. 如果不对变量进行初始化操作,也会被设置为默认值.
实际应用中,不要使用finalize方法回收任何短缺的资源,因为很难知道这个方法在什么时候才调用(jvm自己调用).
类设计技巧
一定要保证数据私有
一定要对数据初始化
不要在类种使用过多的基本类型
不是所有的成员变量都需要独立的getter和setter方法
将职责过多的类分解
类名和方法名要能够体现它们的职责
继承
super只是一个指示编译器调用父类方法的特殊关键字;不是一个对象的引用,而this指的是指向对象本身的引用.
在子类中可以增减成员变量,增加方法或覆盖父类中的方法,然而绝对不能删除继承的任何成员变量和方法.
使用super调用父类的构造方法时必须是子类构造器的第一条语句.(先有父类对象才有子类对象.)
is-a规则,表明子类的每个对象也是父类的对象,这个规则可以用来判断是否应该设计为继承关系.
在Java中,对象变量是多态的.一个父类A既可以引用一个父类A的对象,也可以引用一个父类A的任何一个子类的对象.
子类可以转化为父类(向上转型),但父类不一定能够转换为子类(需要强制类型转换(向下转型)).因为父类可以有多个子孙继承链.
final修饰的类表明该类不可被修改(对象不可被修改),不可被继承.其中的方法都自动的成为final方法,而成员变量则不会被自动生命成final成员变量.
final修饰的方法则表示该方法不可被子类重写.
final修饰的成员变量表示构造对象之后就不能改变它们的值了.
将方法或类声明为final的主要目的是:确保它们在子类中不会被改变语义.而如果将变量声明为final将会提高少许性能(即时编译器),也可以提高线程安全性.
java中进行类型转换的唯一原因是:在暂时忽视对象的实际类型之后,使用对象的全部功能.
编译器仅允许变量调用类中存在的方法.
使用抽象类的两种方式:
在子类中定义部分抽象方法或抽象方法也不定义,这样子类也必须为抽象类
定义全部的抽象方法,这样子类就不是抽象类了
抽象类不能被实例化,但是可以有构造方法.抽象类可以创建一个具体子类的对象.
抽象类可以做为一个对象变量,其值等于具体子类对象的引用.
抽象类中也可以定义具体的实现方法和变量,并且可以通过子类对象的引用进行方法的调用.
java的四个访问修饰符
public
protected
private
默认,无修饰符
编写完美equals方法的建议:
显式参数命令为otherObject,稍后需要将它转换成另一个叫做other的变量
检测this与otherObject是否引用同一个对象:`**if (this == otherObject) return true;**`
检测otherObject是否为null,如果为null,返回false;`if (otherObject == null ) return false;`
比较this与otherObject是否属于同一个类.如果equals的语义在每个子类中都有锁改变,则会getClass检测:`**if (getClass() != otherObject.getClass()) return false;**`;如果所有的子类哦都拥有统一的语义,就使用instanceof检测:`**if(!(otherObject instanceof ClassName)) return false;**`
将otherObject转换为相应的类类型变量`**ClassName other = (ClassName) otherObject**`
对比所有的成员变量.如果在子类中重新定义了equals,就要再其中包含调用`**super.equals(other)**`;
如果重新定义equals方法,就必须重新定义hashCode方法.
hashCode方法应该返回一个整型数值(也可以是负数)
随处可见toString方法的主要原因是:只要对象与一个字符串通过操作符”+”连接起来,Java编译就会自动的调用toString方法,一边获得这个对象的字符串描述.
ArrayList相当于一个size可变的数组
对象包装器是不可变的,即一旦构造了包装器,就不允许更改包装在其中的值.
泛型类型不能是一个基础数据类型.只能是包装类型.
Integer等包装类做比较的时候也应该用`equals`方法.
比较两个枚举类型的值时,永远不需要调用`equals`,而直接使用`==`就可以了.
反射的功能:
在运行中分析类的能力
在运行中查看对象,例如,编写一个toString方法供所有类使用.
实现通用的数组操作代码.
利用Method对象,这个对象很像C++的函数指针.
使用反射的主要人员应该是工具构造者,而不是应用程序员.
Class类在程序运行期间,Java运行时系统始终未所有的对象维护一个被称为运行时的类型标识.这个信息跟踪着每个对象所属的类.虚拟机利用运行时类型信息选择相应的方法执行
可以通过`对象变量.getClass()`来获取Class对象.也可以通过`Class.forName("xxxx")`来获取对应类名的Class对象
一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类.例如基本数据类型int不是类,但是int.class是一个Class类型的对象.
使用`==`运算符来实现两个类对象的比较操作
- `newInstance()`方法用来调用默认的构造器初始化新创建的对象.如果这个类没有默认的构造器,则抛出一个异常.
继承设计的技巧
将公共操作和成员变量放在父类中.
不要使用受保护的成员变量.原因有一个,一个是子类集合是无限制的.任何一个子类都可以编写代码直接访问protected的成员变量,从而破坏了封装性.第二个原因是在Java中,在同一个包中的所有类都可以访问protected的成员变量,而不管它是否为这个类的子类. 不过,protected方法对于指示那些不提供一般用途而应在子类中重新定义的方法很有用
使用继承实现”is-a”关系
除非所有继承的方法都有意义,否则不要使用继承.
在覆盖方法时,不要改变预期的行为. 编译器不会检查重新定义的方法是否有意义.
使用多态,而非类型信息.
如果action1与action2表示的相同的概念.就应该为这个概念定义一个方法,并将其放置在两个类的父类或者接口中.然后就可以调用x.action();
- 不要过多的使用反射.