目录
面向对象
多态性
多态性,是面向对象中最重要的概念,在Java中的体现:对象的多态性:父类的引用指向子类的对象
父类类型 变量名 = 子类对象;
例如
Father f = new Son();
上面这种情况,当Son类重写了方法时,f会调用Son的方法
在编译时,f被认为是Father类,在运行时被认为是Son类:编译时,看左边;运行时,看右边。
多态的使用前提:① 类的继承关系 ② 方法的重写
属性不具备多态性,调f的属性一定是来自于Father,且无法访问 到Son类的属性
f也无法调用Son类特有的方法(弊端)
使用场景
现在我定义了三个类:人,男人,女人,之间存在继承关系
class person{
public void eat(){
System.out.println("人吃饭");
}
}
class man extends person {
public void eat(){
System.out.println("男人吃饭");
}
public void work(){
System.out.println("男人工作");
}
}
class woman extends person {
public void eat(){
System.out.println("女人吃饭");
}
}
在另外一个类中我声明了一个方法,我希望能调用不同类的eat方法:
public class test {
public static void main(String[] args){
test tt = new test();
tt.eating(new man());//男人吃饭
}
public void eating(person p){
p.eat();
}
}
上面这种情况,方法在声明的时候,形参写的是person类,但是传入的是man类,调用的也是man类的方法,这就用到了多态
如果没有多态,就得定义三个重载eating函数了
向下转型
类似于强制类型转换,在编译中一直认为f是Father类,那么只需要将f强制转换为man类就可以调用man类中独有的方法和属性
public static void main(String[] args){
test tt = new test();
person p = new man();
man m = (man)p;
m.work();
}
此处m和p的地址是一样的,其实相当于内存中已经加载了man和person的内容,只是在调用的时候有一些限制,现在强制转换之后可以就行调用了,用的是同一块地址
但是下面这种就不可以,因为内存中没有加载man的方法和属性
public static void main(String[] args){
test tt = new test();
person p = new woman();
man m = (man)p;
m.work();
}
instanceof判断实例属于的类,在向下转型的时候可以先判断一下
person p = new man();
System.out.println(p instanceof person);//true
System.out.println(p instanceof man);//true
System.out.println(p instanceof woman);//true
Object
类 java.lang.Object
是类层次结构的根类,即所有其它类的父类。每个类都使用 Object
作为超类。
Object类型的变量与除Object以外的任意引用数据类型的对象都存在多态引用
method(Object obj){…} //可以接收任何类作为其参数
Person o = new Person();
method(o);
Object方法:
equals()
在object类中,这个方法的作用是比较两个对象的地址是否一样
public static void main(String[] args) throws InterruptedException {
man p1 = new man();
man p2 = new man();
System.out.println(p1.equals(p2));//false
}
但是在某些引用数据类型上,这个方法可能被重写了,例如在String类中,它被重写为判断两个字符串内容是不是一样,类似的还有File、Date类
public static void main(String[] args) throws InterruptedException {
String s1 = "abcdefg";
String s2 = "abcdefg";
int[] a1 = {1,2,3,4};
int[] a2 = {1,2,3,4};
System.out.println(s1.equals(s2));//true
System.out.println(a1.equals(a2));//false
}
这个和 == 的区别就是:
== 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型就是比较内存地址
equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是==;String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
具体要看自定义类里有没有重写Object的equals方法来判断。
通常情况下,重写equals方法,会比较类中的相应属性是否都相等
==如果两端数据类型不一样会报错
toString()
① 默认情况下,toString()返回的是“对象的运行时类型 @ 对象的hashCode值的十六进制形式"
② 在进行String与其它类型数据的连接操作时,自动调用toString()方法
③ 如果我们直接System.out.println(对象),默认会自动调用这个对象的toString()
④ 可以根据需要在用户自定义类型中重写toString()方法
如String 类重写了toString()方法,返回字符串的值。
clone()
对象的克隆,使用时有一些要求:
1、实现Cloneable接口
2、重写clone方法
3、在使用时必须使用try catch捕获异常
public class test {
public static void main(String[] args){
test tt = new test();
man p = new man();
p.name=33;
try {
man p2 = (man)(p.clone());
System.out.println(p2.name);//33
System.out.println(p2 == p);//false
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
class man implements Cloneable{
int age = 1;
int name = 22;
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
注意:Object中的clone方法是浅拷贝
finalize()
- 当对象被回收时,系统自动调用该对象的 finalize() 方法。(不是垃圾回收器调用的,是本类对象调用的)
- 永远不要主动调用某个对象的finalize方法,应该交给垃圾回收机制调用。
- 什么时候被回收:当某个对象没有任何引用时,JVM就认为这个对象是垃圾对象,就会在之后不确定的时间使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用 finalize()方法。
- 子类可以重写该方法,目的是在对象被清理之前执行必要的清理操作。比如,在方法内断开相关连接资源。
- 如果重写该方法,让一个新的引用变量重新引用该对象,则会重新激活对象。
- 在JDK 9中此方法已经被
标记为过时
的。
也需要在类中重写方法
public class test {
public static void main(String[] args) throws InterruptedException {
test tt = new test();
man p = new man();
p = null;
System.gc(); //释放空间
}
}
class man implements Cloneable{
protected void finalize() throws Throwable{
System.out.println("对象被释放");
}
}
Static
如果想让一个成员变量被类的所有实例所共享,就用static修饰即可,称为类变量(或类属性、静态变量)
静态变量:
public class test {
public static void main(String[] args) throws InterruptedException {
man m = new man();
man m2 = new man();
System.out.println(m.country);//cn
System.out.println(m2.country);//cn
m.country = "China";
System.out.println(m.country);//China
System.out.println(m2.country);//China
}
}
class man {
static String country = "cn";
}
静态变量的默认值规则和实例变量一样。
静态变量值是所有对象共享。
静态变量在本类中,可以在任意方法、代码块、构造器中直接使用。
如果权限修饰符允许,在其他类中可以通过“
类名.静态变量
”直接访问,也可以通过“对象.静态变量
”的方式访问(但是更推荐使用类名.静态变量的方式)。静态变量的get/set方法也静态的,当局部变量与静态变量
重名时
,使用“类名.静态变量
”进行区分。在jdk6之前,静态变量放在方法区,jdk7之后放在堆空间
静态方法
- 静态方法在本类的任意方法、代码块、构造器中都可以直接被调用。
- 只要权限修饰符允许,静态方法在其他类中可以通过“类名.静态方法“的方式调用。也可以通过”对象.静态方法“的方式调用(但是更推荐使用类名.静态方法的方式)。
- 在static方法内部只能访问类的static修饰的属性或方法,不能访问类的非static的结构。
- 静态方法可以被子类继承,但不能被子类重写。
- 静态方法的调用都只看编译时类型。
- 因为不需要实例就可以访问static方法,因此static方法内部不能有this,也不能有super。如果有重名问题,使用“类名.”进行区别。
单例模式
所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。
如果我们要让类在一个虚拟机中只能产生一个对象,我们首先必须将
类的构造器的访问权限设置为private
,这样,就不能用new操作符在类的外部产生类的对象了,但在类内部仍可以产生该类的对象。因为在类的外部开始还无法得到类的对象,只能调用该类的某个静态方法
以返回类内部创建的对象,静态方法只能访问类中的静态成员变量,所以,指向类内部产生的该类对象的变量也必须定义成静态的
。
第一种方式:饿汉式
public class test {
public static void main(String[] args) throws InterruptedException {
Singleton S1 = Singleton.getInstance();
Singleton S2 = Singleton.getInstance();
System.out.println(S1 == S2); // true
}
}
class Singleton{
private Singleton(){}
private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}
}
第二种方式:懒汉式
public class test {
public static void main(String[] args) throws InterruptedException {
Singleton S1 = Singleton.getInstance();
Singleton S2 = Singleton.getInstance();
System.out.println(S1 == S2); // true
}
}
class Singleton{
private Singleton(){}
private static Singleton instance = null;
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
return instance;
}else{
return instance;
}
}
}
饿汉式:
- 特点:
立即加载
,即在使用类的时候已经将对象创建完毕。- 优点:实现起来
简单
;没有多线程安全问题。- 缺点:当类被加载的时候,会初始化static的实例,静态变量被创建并分配内存空间,从这以后,这个static的实例便一直占着这块内存,直到类被卸载时,静态变量被摧毁,并释放所占有的内存。因此在某些特定条件下会
耗费内存
。懒汉式:
- 特点:
延迟加载
,即在调用静态方法时实例才被创建。- 优点:实现起来比较简单;当类被加载的时候,static的实例未被创建并分配内存空间,当静态方法第一次被调用时,初始化实例变量,并分配内存,因此在某些特定条件下会
节约内存
。- 缺点:在多线程环境中,这种实现方法是完全错误的,
线程不安全
,根本不能保证单例的唯一性。
代码块
1、代码块是在类中直接以 {} 包含的一段代码,主要功能是进行初始化
2、其修饰前缀只能是 static ,故可以分为静态代码块和非静态代码块
3、静态代码块随着 类 加载而执行,所以只会执行一次,而非静态代码块随着 对象 加载和执行,可以执行多次
public class test {
public static void main(String[] args) throws InterruptedException {
System.out.println(Singleton.age);//静态代码块 3
System.out.println(Singleton.age);//3
Singleton S1 = new Singleton();//非静态代码块
Singleton S2 = new Singleton();//非静态代码块
}
}
class Singleton{
public static int age = 3;
{
System.out.println("非静态代码块");
}
static {
System.out.println("静态代码块");
}
}
4、静态代码块不能调用非静态的属性和方法,非静态代码块可以
5、执行顺序是:静态代码块>非静态代码块>构造方法
public class test {
public static void main(String[] args) throws InterruptedException {
Singleton S1 = new Singleton();//3333 2222 1111
}
}
class Singleton{
public Singleton(){
System.out.println("1111");
}
{
System.out.println("2222");
}
static {
System.out.println("3333");
}
}
6、代码块可以写多个,同类代码块之间的执行顺序按照声明的顺序
final
final:最终的,不可更改的
final修饰类
表示这个类不能被继承,没有子类。提高安全性,提高程序的可读性。
final class Eunuch{//太监类
}
class Son extends Eunuch{//错误
}
final修饰方法
表示这个方法不能被子类重写。
class Father{
public final void method(){
System.out.println("father");
}
}
class Son extends Father{
public void method(){//错误
System.out.println("son");
}
}
final修饰变量
final修饰某个变量(成员变量或局部变量),一旦赋值,它的值就不能被修改,即常量,常量名建议使用大写字母。
如果某个成员变量用final修饰后,并且必须初始化(可以显式赋值、或在初始化块赋值、实例变量还可以在构造器中赋值)
抽象类与抽象方法(或abstract关键字)
随着继承层次中一个个新子类的定义,类变得越来越具体,而父类则更一般,更通用。类的设计应该保证父类和子类能够共享特征。有时将一个父类设计得非常抽象,以至于它没有具体的实例,这样的类叫做抽象类。
我们声明一些几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长。那么这些共同特征应该抽取到一个共同父类:几何图形类中。但是这些方法在父类中又无法给出具体的实现
,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体
,我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类。
抽象类
[权限修饰符] abstract class 类名{
}
[权限修饰符] abstract class 类名 extends 父类{
}
抽象方法
抽象方法没有方法体和大括号
[其他修饰符] abstract 返回值类型 方法名([形参列表]);
1、抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
2、抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。
3、抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
4、抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
5、不能用abstract修饰变量、代码块、构造器;不能用abstract修饰私有方法、静态方法、final的方法、final的类。
接口
在JDK8.0 之前,接口中只允许出现:
(1)公共的静态的常量:其中
public static final
可以省略(2)公共的抽象的方法:其中
public abstract
可以省略
类可以实现多个接口,一定程度上弥补了单继承的局限性
1、如果接口的实现类是非抽象类,那么必须
重写接口中所有抽象方法
2、默认方法可以选择保留,也可以重写
3、接口中的静态方法不能被继承也不能被重写
public class test {
public static void main(String[] args){
Bird bird = new Bird();
bird.fly();
System.out.println(bird.MIN_SPEED);
}
}
interface flyable{ //接口
public static final int MIN_SPEED = 0;
public abstract void fly();
}
interface eatable{
int mouth = 1;
void eat();
}
class Bird implements flyable,eatable{
@Override
public void fly() {
System.out.println("鸟可以飞");
}
@Override
public void eat() {
System.out.println("鸟可以吃东西");
}
}
接口之间是可以继承的,且可以实现多继承,子接口没有什么限制,但是接入子接口的类必须重写所有接口的方法
interface flyable{
public static final int MIN_SPEED = 0;
public abstract void fly();
}
interface eatable{
int mouth = 1;
void eat();
}
interface fly_and_eat extends flyable,eatable{
}
接口的多态性
实现类实现接口,类似于子类继承父类,因此,接口类型的变量与实现类的对象之间,也可以构成多态引用。通过接口类型的变量调用方法,最终执行的是你new的实现类对象实现的方法体。
类似于类的多态性:
[接口] 接口名 = new [实现类]
先定义接口和类:
interface USB{
void start();
void end();
}
class Computer{
public void print(USB usb){ //形参是接口,但是传入实现类的对象
usb.start();
usb.end();
}
}
class Printer implements USB{
@Override
public void start() {
System.out.println("开始连接打印机");
}
@Override
public void end() {
System.out.println("结束连接打印机");
}
}
有三种实现多态的方法:
public class test {
public static void main(String[] args){
Computer computer = new Computer();
Printer printer = new Printer();
//创建接口实现类的对象
computer.print(printer);
//创建接口实现类的匿名对象
computer.print(new Printer());
//创建接口匿名实现类的对象
USB usb = new USB() {
@Override
public void start() {
System.out.println("开始连接U盘");
}
@Override
public void end() {
System.out.println("结束连接U盘");
}
};
computer.print(usb);
}
}
接口的默认方法
接口中的方法也可以有方法体,但是需要设置为 默认:
public class test {
public static void main(String[] args){
Printer printer = new Printer();
printer.test();
}
}
interface USB{
public default void test(){
System.out.println("默认方法的方法体");
}
}
class Printer implements USB{
}
此处必须声明default,不能省略,否则会认为是 抽象方法
接口冲突:
若两个接口中定义了两个一样的默认方法,而实现类同时接入两个接口,就会产生接口冲突,该实现类需要重写该方法:
interface USB{
public default void test(){
System.out.println("默认方法的方法体");
}
}
interface USB1{
public default void test(){
System.out.println("默认方法的方法体——2");
}
}
class Printer implements USB,USB1{
@Override
public void test() {
System.out.println("方法重写");
}
}
但是如果其继承的父类也有一样的方法就没有问题,因为继承父类的优先级更高
interface USB{
public default void test(){
System.out.println("默认方法的方法体");
}
}
interface USB1{
public default void test(){
System.out.println("默认方法的方法体——2");
}
}
class machine{
public void test(){
System.out.println("父类方法");
}
}
class Printer extends machine implements USB,USB1{
}
在实现类中也可以调用分别调用接口的方法
class Printer extends machine implements USB,USB1{
@Override
public void test() {
super.test();
USB.super.test();
USB1.super.test();
// 父类方法
// 默认方法的方法体
// 默认方法的方法体——2
}
}
内部类
将一个类A定义在另一个类B里面,里面的那个类A就称为内部类(InnerClass)
,类B则称为外部类(OuterClass)
。
具体来说,当一个事物A的内部,还有一个部分需要一个完整的结构B进行描述,而这个内部的完整的结构B又只为外部事物A提供服务,不在其他地方单独使用,那么整个内部的完整结构B最好使用内部类。
分类:
成员内部类
public class test {
public static void main(String[] args){
//声明静态内部类
person.man m1 = new person.man();
//声明非静态内部类
person p = new person();
person.woman w1 = p.new woman();
m1.eat();
w1.eat();
}
}
class person{
static class man{
public void eat(){
System.out.println("man eat");
}
}
class woman{
public void eat(){
System.out.println("woman eat");
}
}
}
显然静态成员内部类不能调用外部类的方法和属性
非静态成员内部类可以调用外部类的方法和属性,但是需要 person.this.xx
class person{
public void showage(){
System.out.println(this.age);
}
int age = 3;
class woman{
int age = 4;
public void eat(){
System.out.println("woman eat");
}
public void getage(){
System.out.println(age); //4
System.out.println(person.this.age);//3
person.this.showage();//3
}
}
}
局部内部类
非匿名内部类:
public class test {
public static void main(String[] args){
person p = new person();
eater m1 = p.get_a_man();
m1.eat(); //man eat
p.show_eat();//the man is eating
}
}
interface eater{
void eat();
}
class person{
public eater get_a_man(){
class man implements eater{
public void eat(){
System.out.println("man eat");
}
}
return new man();
}
public void show_eat(){
class man {
public void eat(){
System.out.println("the man is eating");
}
}
new man().eat();
}
}
上面写了两种情况,一种是返回了对象,一种是只有操作
对于返回对象的情况,必须要继承一个类或者接口,下面这种写法是无法调用到内部方法的:
class person{
public Object get_a_man(){
class man{
public void eat(){
System.out.println("man eat");
}
}
return new man();
}
}
匿名内部类:
使用匿名内部类的对象直接调用方法
public class test {
public static void main(String[] args){
new Object(){
public void say(){
System.out.println("hhhh");
}
}.say();
}
}
通过父类或父接口的变量多态引用匿名内部类的对象
interface A{
void say();
}
public class test {
public static void main(String[] args){
A obj = new A(){
public void say(){
System.out.println("hhhh");
}
};
obj.say();
}
}
枚举类
枚举类型本质上也是一种类,只不过是这个类的对象是有限的、固定的几个,不能让用户随意创建。
例如星期的类,那么对象只会有7个
5.0之前,实际上就是在类内部自己定义好可能的对象,并设置为静态final对象
public class test {
public static void main(String[] args){
System.out.println(Season.SPRING.toString());
//Season{SEASONNAME='春天', SEASONDESC='春暖花开'}
}
}
class Season{
private final String SEASONNAME;//季节的名称
private final String SEASONDESC;//季节的描述
private Season(String seasonName,String seasonDesc){
this.SEASONNAME = seasonName;
this.SEASONDESC = seasonDesc;
}
public static final Season SPRING = new Season("春天", "春暖花开");
public static final Season SUMMER = new Season("夏天", "夏日炎炎");
public static final Season AUTUMN = new Season("秋天", "秋高气爽");
public static final Season WINTER = new Season("冬天", "白雪皑皑");
@Override
public String toString() {
return "Season{" +
"SEASONNAME='" + SEASONNAME + '\'' +
", SEASONDESC='" + SEASONDESC + '\'' +
'}';
}
}
jdk5.0中,可以使用enum声明
- 枚举类的常量对象列表必须在枚举类的首行,因为是常量,所以建议大写。
- 列出的实例系统会自动添加 public static final 修饰。
- 如果常量对象列表后面没有其他代码,那么“;”可以省略,否则不可以省略“;”。
- 编译器给枚举类默认提供的是private的无参构造,如果枚举类需要的是无参构造,就不需要声明,写常量对象列表时也不用加参数
- 如果枚举类需要的是有参构造,需要手动定义,有参构造的private可以省略,调用有参构造的方法就是在常量对象名后面加(实参列表)就可以。
- 枚举类默认继承的是java.lang.Enum类,因此不能再继承其他的类型。
- JDK5.0 之后switch,提供支持枚举类型,case后面可以写枚举常量名,无需添加枚举类作为限定。
public class test {
public static void main(String[] args){
System.out.println(SeasonEnum.SPRING.getSeasonName());
}
}
enum SeasonEnum {
SPRING("春天","春风又绿江南岸"),
SUMMER("夏天","映日荷花别样红"),
AUTUMN("秋天","秋水共长天一色"),
WINTER("冬天","窗含西岭千秋雪");
private final String seasonName;
private final String seasonDesc;
private SeasonEnum(String seasonName, String seasonDesc) {
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
}
enum常用方法:
public class test {
public static void main(String[] args){
System.out.println(SeasonEnum.SUMMER);
System.out.println(SeasonEnum.SPRING.name());
SeasonEnum[] values = SeasonEnum.values();
System.out.println(Arrays.toString(values));
// SUMMER
// SPRING
//[SPRING, SUMMER, AUTUMN, WINTER]
SeasonEnum s1 = SeasonEnum.valueOf("AUTUMN");
System.out.println(s1);//Autumn
}
}
实现接口的枚举类
每个对象单独重写接口方法
interface season_desc{
void show();
}
enum SeasonEnum implements season_desc{
SPRING("春天","春暖花开"){
public void show(){
System.out.println("春天在哪里?");
}
},
SUMMER("夏天","夏日炎炎"){
public void show(){
System.out.println("宁静的夏天");
}
},
AUTUMN("秋天","秋高气爽"){
public void show(){
System.out.println("秋天是用来分手的季节");
}
},
WINTER("冬天","白雪皑皑"){
public void show(){
System.out.println("2002年的第一场雪");
}
};
private final String seasonName;
private final String seasonDesc;
private SeasonEnum(String seasonName, String seasonDesc) {
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
}
注解(Annotation)
注解(Annotation)是从JDK5.0
开始引入,以“@注解名
”在代码中存在。例如:
@Override
@Deprecated
@SuppressWarnings(value=”unchecked”)
注解是可以被编译器或其他程序读取的。程序还可以根据注解的不同,做出相应的处理。
@author 标明开发该类模块的作者,多个作者之间使用,分割 @version 标明该类模块的版本 @see 参考转向,也就是相关主题 @since 从哪个版本开始增加的 @param 对方法中某参数的说明,如果没有参数就不能写 @return 对方法返回值的说明,如果方法的返回值类型是void就不能写 @exception 对方法可能抛出的异常进行说明 ,如果方法没有用throws显式抛出的异常就不能写
@Override
: 限定重写父类方法,该注解只能用于方法
@Deprecated
: 用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
@SuppressWarnings
: 抑制编译器警告
包装类
为了使得基本数据类型具备引用数据类型的相关特征
也就是把基本数据类型转换为 obj
public static void main(String[] args){
int num = 520;
Integer obj = new Integer(520);
}
相互转换:
1、将基本数据类型转换为引用数据类型
Integer a = Integer.valueOf(10);
System.out.println(a);//3
Float b = Float.valueOf(12.3f);
System.out.println(b);//12.3
Float c = Float.valueOf("12.4f");
System.out.println(c); //12.4
Boolean d = Boolean.valueOf("sad");
System.out.println(d);//false
2、将引用数据类型转换为基本数据类型
Integer a = Integer.valueOf(10);
System.out.println(a.intValue());
Float b = Float.valueOf(12.3f);
System.out.println(b.floatValue());
3、自动转换
由于我们经常要做基本类型与包装类之间的转换,从JDK5.0
开始,基本类型与包装类的装箱、拆箱动作可以自动完成。例如:
Integer a = 1;
Float b=3.13f;
Boolean c = true;
int d = a;
float e = b;
boolean f = c;
包装类的其它API
数据类型的最大最小值
Integer.MAX_VALUE和Integer.MIN_VALUE
Long.MAX_VALUE和Long.MIN_VALUE
Double.MAX_VALUE和Double.MIN_VALUE
字符转大小写
Character.toUpperCase('x');
Character.toLowerCase('X');
整数转进制
Integer.toBinaryString(int i)
Integer.toHexString(int i)
Integer.toOctalString(int i)
比较的方法
Double.compare(double d1, double d2)
Integer.compare(int x, int y)
包装类对象的特点
Integer a = 1;
Integer b = 1;
System.out.println(a == b);//true
Integer i = 128;
Integer j = 128;
System.out.println(i == j);//false
Integer m = new Integer(1);//新new的在堆中
Integer n = 1;//这个用的是缓冲的常量对象,在方法区
System.out.println(m == n);//false
Integer x = new Integer(1);//新new的在堆中
Integer y = new Integer(1);//另一个新new的在堆中
System.out.println(x == y);//false
Double d1 = 1.0;
Double d2 = 1.0;
System.out.println(d1==d2);//false 比较地址,没有缓存对象,每一个都是新new的
Integer i = 1000;
double j = 1000;
System.out.println(i==j);//true 会先将i自动拆箱为int,然后根据基本数据类型“自动类型转换”规则,转为double比较
Integer i = 1000;
int j = 1000;
System.out.println(i==j);//true 会自动拆箱,按照基本数据类型进行比较
Integer i = 1;
Double d = 1.0
System.out.println(i==d);//编译报错
包装类对象不可变
public class TestExam {
public static void main(String[] args) {
int i = 1;
Integer j = new Integer(2);
Circle c = new Circle();
change(i,j,c);
System.out.println("i = " + i);//1
System.out.println("j = " + j);//2
System.out.println("c.radius = " + c.radius);//10.0
}
/*
* 方法的参数传递机制:
* (1)基本数据类型:形参的修改完全不影响实参
* (2)引用数据类型:通过形参修改对象的属性值,会影响实参的属性值
* 这类Integer等包装类对象是“不可变”对象,即一旦修改,就是新对象,和实参就无关了
*/
public static void change(int a ,Integer b,Circle c ){
a += 10;
// b += 10;//等价于 b = new Integer(b+10);
c.radius += 10;
/*c = new Circle();
c.radius+=10;*/
}
}
class Circle{
double radius;
}