String s=new String("123")创建了几个对象?

String str=new String("123");   紧接着这段代码之后的往往是这个问题,那就是这行代码究竟创建了几个String对象呢?


相信大家对这道题并不陌生,答案也是众所周知的,2个。


接下来我们就从这道题展开,一起回顾一下与创建String对象相关的一些JAVA知识。  


我们可以把上面这行代码分成String str、=、"123"和new String()四部分来看待。String str只是定义了一个名为str的String类型的变量,因此它并没有创建对象;=是对变量str进行初始化,将某个对象的引用(或者叫句柄)赋值给它,显然也没有创建对象;现在只剩下new String("123")了。那么,new String("123")为什么又能被看成"123"和new String()呢?


我们来看一下被我们调用了的String的构造器:  


public String(String original) {  //other code ...  }   大家都知道,我们常用的创建一个类的实例(对象)的方法有以下两种:


一、使用new创建对象。 


二、调用Class类的newInstance方法,利用反射机制创建对象。


我们正是使用new调用了String类的上面那个构造器方法创建了一个对象,并将它的引用赋值给了str变量。同时我们注意到,被调用的构造器方法接受的参数也是一个String对象,这个对象正是"123"。由此我们又要引入另外一种创建String对象的方式的讨论——引号内包含文本。


 


这种方式是String特有的,并且它与new的方式存在很大区别。  


String str="123";  


毫无疑问,这行代码创建了一个String对象。  


String a="123";  String b="123";   那这里呢?


答案还是一个。  


String a="123"+"456";   再看看这里呢?


答案是三个。
说到这里,我们就需要引入对字符串池相关知识的回顾了。  


在JAVA虚拟机(JVM)中存在着一个字符串池,其中保存着很多String对象,并且可以被共享使用,因此它提高了效率。由于String类是final的,它的值一经创建就不可改变,因此我们不用担心String对象共享而带来程序的混乱。字符串池由String类维护,我们可以调用intern()方法来访问字符串池。  


我们再回头看看String a="123";,这行代码被执行的时候,JAVA虚拟机首先在字符串池中查找是否已经存在了值为"123"的这么一个对象,它的判断依据是String类equals(Object obj)方法的返回值。如果有,则不再创建新的对象,直接返回已存在对象的引用;如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。因此,我们不难理解前面三个例子中头两个例子为什么是这个答案了。


 


只有使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中。对于所有包含new方式新建对象(包括null)的“+”连接表达式,它所产生的新对象都不会被加入字符串池中,对此我们不再赘述。因此我们提倡大家用引号包含文本的方式来创建String对象以提高效率,实际上这也是我们在编程中常采用的。


 


栈(stack):主要保存基本类型(或者叫内置类型)(char、byte、short、int、long、float、double、boolean)和对象的引用,数据可以共享,速度仅次于寄存器(register),快于堆。 


堆(heap):用于存储对象


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
基本数据类型的包装类 •八大数据类型的包装类分别为:Byte、Short、Integer、Long、Character、 Float、Double、Boolean。 把基本数据类型变量包装类实例是通过对应包装类的构造器来实现的,不仅如此,8个包装类中除了 Character之外,还可以通过传入一个字符串参数来构建包装类对象。 •如果希望获得包装类对象中包装的基本类型变量,则可以使用包装类提供的XxxValue()实例方法。 自动装箱与自动拆箱 •JDk还提供了自动装箱和自动拆箱。自动装箱就是把一个基本类型的变量直接赋给对应的包装类变量,自动拆箱 则与之相反。 •包装类还可以实现基本类型变量和字符串之间的转换,除了Character之外的所有包装类都提供了一个 parseXxx(String s)静态方法。 •如果将基本类型转换为这符串,只需在后面加+ “”进行连接运算。 Java 7对包装类的增强 •Java 7为所有包装类增加一个新方法: compare(x , y)的方法。该方法用于比较两个包装类实例,当x>y, 返回大于0的数;当x==y,返回0;否则返回小于0的数。 对象的方法 •打印对象和toString方法:toString方法是系统将会输出该对象的“自我描述”信息,用以告诉外界对象具有的状 态信息。 •Object 类提供的toString方法总是返回该对象实现类的类名 + @ +hashCode值。 •==和equals比较运算符:==要求两个引用变量指向同一个对象才会返回true。equals方法则允许用户提供自 定义的相等规则。 •Object类提供的equals方法判断两个对象相等的标准与==完全相同。因此开发者通常需要重写equals方法。 类成员 •在java类里只能包含Field,方法,构造器,初始化块,内部类(接口、枚举)等5种成员。 用static修饰的类成员属 于类成员,类Field既可通过类来访问,也可以通过类的对象来访问。当通过对象来访问类属性时,系统会在底 层转换为通过该类来访问类 属性。 类成员规则 •类成员并不是属于实例,它是属于类本身的。只要类存在,类成员就存在。 •即使通过null对象来访问类成员,程序也不会引发NullPointerException。   类成员不能访问实例成员。 单例类 •如果一个类始终只能创建一个对象,称为单例类。须符合以下几个条件:   –1.我们把该类的构造器使用Private修饰,从而把该 类的所有构造器隐藏起来。   –2.则需要提供一个public方法作为该类的访问点,用于创建该类的对象,且必须使用static修饰   –3.该类还必须缓存已经创建对象,必须用static修饰 final变量 •final修饰变量时,表示该变量一旦获得 初始值之后就不可被改变。 •final既可修饰成员变量,也可以修饰局部变量。 final修饰成员变量 •成员变量是随类的初始化或对象初始化而初始化的。final修饰的成员变量必须由程序员指定初始值。 •对于类属性而言,要么在静态初始化中初始化,要么在声明该属性时初始化。 •对于实例属性,要么在普通初始化块中指定初始值。要么在定义时、或构造器中指定初始值。 final修饰局部变量 •使用final修饰局部变量时既可以在定义时指定默认值,也可以不指定默认值。 •给局部变量赋初始值,只能一次,不能重复。 final修饰基本类型和引用类型 •当使用final修饰基本数据类型时,不能对其重新赋值,不能被改变。 •但对引用类型的变量而言,它仅仅保存的是一个引用,final只能保证他的地址不变,但不能保证对象,所以引用 类型完全可以改变他的对象。 可执行“宏替换”的final变量 •对一个final变量来说,不管它是类变量、实例变量,还是局部变量,只要该变量满足3个条件,这个final变量就 不再是一个变量,而是相当于一个直接量。   –使用final修饰符修饰;   –在定义该final变量时指定了初始值;   –该初始值可以在编译时就被确定下来。 final方法 •final方法 •final 修饰的方法不可以被重写。 •final 修饰的方法仅仅是不能重写,但它完全可以被重载。 •final 修饰的类不可以被继承 不可变的类 •不可变的类要满足以下几个条件:   –1.使用private和final修饰符来修饰该类的属性   –2.提供带参数的构造器,用于根据传入参数来初始化类里的属性   –3.仅为该类的属性提供getter方法,不要为该类的属性提供setter方法,因为普通方法无法修改final修饰的 属性   –4.如有必要,重写Object类中hashCode 和equals •缓存实例的不可变类:如果程序经常需要使用不可变类的实例,则可对实例进行缓存。 抽象方法和抽象类 •抽象方法和类都必须使用abstract来修饰,有抽象方法的类只能定义成抽象类,抽象里也可以没有抽象方法。 • 抽象类不能被实例化,可以通过其子类给他赋值,普通类里有的抽象里也有,定义抽象方法只需在普通方法上增 加abstract修饰符,并把普通方法的方法体(也就是方法后花括号括起来的部分)全部去掉,并在方法后增加分号 即可。 抽象类的特征 •抽象类的特征:有得有失,得到了新能力,可以拥有抽象方法;失去了创建对象的能力。 抽象类的作用 •抽象类代表了一种未完成的类设计,它体现的是一种模板。 •抽象类与模板模式。 接口的概念 •接口定义的是多个类共同的行为规范,这些行为是与外部交流的通道,这就意味着接口里通常是定义一组公用的 方法。 •接口体现了规范与实现分离的设计。 接口的定义 •和类定义不同,定义接口不再用class关键字,而是使用interface关键字。语法如下: •[修饰符] interface接口名 extends 父接口1,父接口2 ... •{ • 零个到多个常量定义... • 零个到多个抽象方法定义... • 零个到多个内部类、接口、枚举定义... • 零个到多个默认方法或类方法定义... •} 接口里的成分 •在定义接口时,接口里可以包含成员变量(只能是常量),方法(只能是抽象实例方法、类方法或默认方法),内 部类(包括内部接口、枚举类   –常量都是:public static final修饰   –方法都是:public abstract 修饰   –内部的类:public static 接口的继承 •接口的继承和类继承不一样,接口完全支持多继承,子接口扩展某个父接口将会获得父接口的所有抽象方法,常 量属性,内部类和枚举类定义。 使用接口 •接口可以用于声明引用类型的变量,但接口不能用于创建实例。 •当使用接口来声明引用类型的变量时,这个引用类型的变量必须引用到其实现类的对象。 •一个类可以实现一个或多个接口,继承使用extends关键字,实现接口则使用implements关键字。 实现接口 •一个类实现了一个或多个接口之后,这个类必须完全实现这些接口里所定义的全部抽象方法(也就是重写这些抽 象方法); •否则,该类将保留从父接口那里继承到的抽象方法,该类也必须定义成抽象类。 接口和抽象类的相似性 •接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。 •接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。 接口与抽象类的区别 •接口里只能包含抽象方法,不同包含已经提供实现的方法;抽象类则完全可以包含普通方法。 •接口里不能定义静态方法;抽象类里可以定义静态方法。 •接口里只能定义静态常量属性,不能定义普通属性;抽象类里则既可以定义普通属性,也可以定义静态常量属 性。 •接口不包含构造器;抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而让其子类调用这些构 造器来完成属于抽象类的初始化操作。 •接口里不能包含初始化块,但抽象类则完全可以包含初始化块。 •一个类最多只能有一个直接父类,包括抽象类;但一个类可以直接实现多个接口,通过实现多个接口可以弥补 Java单继承的不足。 面向接口编程 •接口体现了规范与实现分离的原则。充分利用接口可以很好地提高系统的可扩展性和可维护性。 •接口与简单工厂模式、命令模式等。 内部类 •我们把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类,有的也叫嵌套类,包含内   部类的类也被称为外部类有的也叫宿住类。 •内部类提供了更好的封装,内部类成员可以直接访问外部类的私有数据,因为内部类被当成其他外部类成员。 •匿名内部类适合用于创建那些仅需要一次使用的类。 非静态内部类 •定义内部类非常简单,只要把一个类放在另一个类内部定义即可。 •当在非静态内部类的方法内访问某个变量时,系统优先在该方法内查找是否存在该名字的局部变量,如果存在该 名字的局部变量,就使用该变量,如果不存在,则到该方法所在的内部类中查找是否存在该名字的属性,如果存在 则使用该属性。 •总之,第一步先找局部变量,第二步,内部类的属性,第三步。外部类的属性。 本文原创作者:pipi-changing 本文原创出处:http://www.cnblogs.com/pipi-changing/ 静态内部类 •如果用static修饰一个内部类,称为静态内部类。 •静态内部类可以包含静态成员,也可以包含非静态成员。所以静态内部类不能访问外部类的实例成员,只能访问   外部类的类成员。 •静态内部类的对象寄存在外部类里,非静态内部类的对象寄存在外部类实例里 使用内部类 •1.在外部类内部使用内部类-不要在外部类的静态成员中使用非静态内部类,因为静态成员不能访问非静态成 员。 • 2.在外部类以外使用非静态内部类。   –private 修饰的内部类只能在外部类内部使用。   –在外部类以外的地方使用内部类,内部类完整的类名应该OuterClass.InnerClass.   –在外部类以外的地方使用非静态内部类创建对象的语法如下:OuterInstance.new InnerConstructor()   –在外部类以外的地方使用静态内部类创建对象的语法如下:new OuterClass.InnerConstructer(); 局部内部类 •如果把一个内部类放在方法里定义,这就是局部内部类,仅仅在这个方法里有效。 •局部内部类不能在外部类以外的地方使用,那么局部内部类也不能使用访问控制符和static修饰 匿名内部类 •匿名内部类适合创建那种只需要一次使用的类,定义匿名内部类的语法格式如下: •new 父类构造器(实例列表) |实现接口) •{ • //匿名内部类的 类体部分 •} •匿名内部类不能是抽象类,匿名内部类不能定义构造器。 Lambda表达式入门 •Lambda表达式主要作用就是代替匿名内部类的繁琐语法。它由三部分组成:   –形参列表。形参列表允许省略形参类型。如果形参列表中只有一个参数,甚至连形参列表的圆括号也可以省略。   –箭头(->),必须通过英文等号和大于符号组成。   –代码块。如果代码块只有包含一条语句,Lambda表达式允许省略代码块的花括号,如果省略了代码块的花括 号,这条语句不要用花括号表示语句结束。Lambda代码块只有一条return语句,甚至可以省略return关键字。 Lambda表达式需要返回值,而它的代码块中仅有一条省略了return的语句,Lambda表达式会自动返回这条语句的 值。 Lambda表达式与函数式接口 •如果采用匿名内部类语法来创建函数式接口的实例,只要实现一个抽象方法即可,在这种情况下即可采用 Lambda表达式来创建对象,该表达式创建出来的对象的目标类型就是这个函数式接口。 •Lambda表达式有如下两个限制:   –Lambda表达式的目标类型必须是明确的函数式接口。   –Lambda表达式只能为函数式接口创建对象。Lambda表达式只能实现一个方法,因此它只能为只有一个抽 象方法的接口(函数式接口)创建对象。 •为了保证Lambda表达式的目标类型是一个明确的函数式接口,可以有如下三种常见方式:   –将Lambda表达式赋值给函数式接口类型的变量。   –将Lambda表达式作为函数式接口类型的参数传给某个方法。   –使用函数式接口对Lambda表达式进行强制类型转换。 方法引用与构造器引用 种类 示例 说明 对应的Lambda表达式 引用类方法 类名::类方法 函数式接口中被实现方法的全部参数传给该类方法作为参数。 (a,b,...) -> 类名.类方法(a,b, ...) 引用特定对象的实例方法 特定对象::实例方法 函数式接口中被实现方法的全部参数传给该方法作为参数。 (a,b, ...) -> 特定对象.实例方法(a,b, ...) 引用某类对象的实例方法 类名::实例方法 函数式接口中被实现方法的第一个参数作为调用者,后面的参数全部传给该方法作为参数。 (a,b, ...) ->a.实例方法(b, ...) 引用构造器 类名::new 函数式接口中被实现方法的全部参数传给该构造器作为参数。 (a,b, ...) ->new 类名(a,b, ...) Lambda表达式与匿名内部类 •Lambda表达式与匿名内部类存在如下相同点:   –Lambda表达式与匿名内部类一样,都可以直接访问“effectively final”的局部变量,以及外部类的成员变 量(包括实例变量和类变量)。   –Lambda表达式创建对象与匿名内部类生成的对象一样, 都可以直接调用从接口继承得到的默认方法。 •Lambda表达式与匿名内部类主要存在如下区别:   –匿名内部类可以为任意接口创建实例——不管接口包含多少个抽象方法,只要匿名内部类实现所有的抽象方 法即可。但Lambda表达式只能为函数式接口创建实例。   –匿名内部类可以为抽象类、甚至普通类创建实例,但Lambda表达式只能为函数式接口创建实例。   –匿名内部类实现的抽象方法的方法体允许调用接口中定义的默认方法;但Lambda表达式的代码块不允许调 用接口中定义的默认方法。 手动实现枚举类 •可以采用如下设计方式:   –通过private将构造器隐藏起来。   –把这个类的所有可能实例都使用public static final属性来保存。   –如果有必要,可以提供一些静态方法,允许其他程序根据特定参数来获取与之匹配实例。 JDK 5新增的枚举支持 •J2SE1.5新增了一个enum关键字,用以定义枚举类。正如前面看到,枚举类是一种特殊的类,它一样可以有自 己的方法和属性,可以实现一个或者多个接口,也可以定义自己的构造器。一个Java源文件中最多只能定义一个 public访问权限的枚举类,且该Java源文件也必须和该枚举类的类名相同。 枚举类 •枚举类可以实现一个或多个接口,使用enum定义的枚举类默认继承了java.lang.Enum类,而不是继承Object 类。其中java.lang.Enum类实现了java.lang.Serializable和java.lang. Comparable两个接口。 •枚举类的构造器只能使用private访问控制符,如果省略了其构造器的访问控制符,则默认使用private修饰;如 果强制指定访问控制符,则只能指定private修饰符。 •枚举类的所有实例必须在枚举类中显式列出,否则这个枚举类将永远都不能产生实例。列出这些实例时系统会自 动添加public static final修饰,无需程序员显式添加。 •所有枚举类都提供了一个values方法,该方法可以很方便地遍历所有的枚举值。 枚举类的属性、方法和构造器 •枚举类也是一种类,只是它是一种比较特殊的类,因此它一样可以使用属性和方法。 •枚举类通常应该设计成不可变类,也就说它的属性值不应该允许改变,这样会更安全,而且代码更加简洁。为 此,我们应该将枚举类的属性都使用private final 修饰。 •一旦为枚举类显式定义了带参数的构造器,则列出枚举值时也必须对应地传入参数。 实现接口的枚举类 •枚举类也可以实现一个或多个接口。与普通类实现一个或多个接口完全一样,枚举类实现一个或多个接口时,也 需要实现该接口所包含的方法。 •如果需要每个枚举值在调用同一个方法时呈现出不同的行为方式,则可以让每个枚举值分别来实现该方法,每个 枚举值提供不同的实现方式,从而让不同枚举值调用同一个方法时具有不同的行为方式。 包含抽象方法的枚举类 •可以在枚举类里定义一个抽象方法,然后把这个抽象方法交给各枚举值去实现即可。 •枚举类里定义抽象方法时无需显式使用abstract关键字将枚举类定义成抽象类,但因为枚举类需要显式创建枚举 值,而不是作为父类,所以定义每个枚举值时必须为抽象方法提供实现,否则将出现编译错误。 垃圾回收机制 •垃圾回收机制只负责回收堆内存中对象,不会回收任何任何物理资源(例如数据库连接,网络IO等资源)。 •程序无法精确控制垃圾回收的运行,垃圾回收会在合适时候进行垃圾回收。当对象永久性地失去引用后,系统就 会在合适时候回收它所占的内存。 •垃圾回收机制回收任何对象之前,总会先调用它的finalize方法,该方法可能使该对象重新复活(让一个引用变量 重新引用该对象),从而导致垃圾回收机制取消回收 对象在内存中的状态 •激活状态:当一个对象创建后,有一个以上的引用变量引用它。则这个对象在程序中处于激活状态,程序可通 过引用变量来调用该对象的属性和方法。 •去活状态:如果程序中某个对象不再有任何引用变量引用它,它就进入了去活状态。在这个状态下,系统的垃圾 回收机制准备回收该对象所占用的内存,在回收该对象之前,系统会调用所有去活状态对象的finalize方法进行资 源清理,如果系统在调用finalize方法重新让一个引用变量引用该对象,则这个对象会再次变为激活状态;否则该 对象将进入死亡状态。 •死亡状态:当对象与所有引用变量的关联都被切断,且系统会调用所有对象的finalize方法依然没有使该对象变成 激活状态,那这个对象将永久性地失去引用,最后变成死亡状态。只有当一个对象处于死亡状态时,系统才会真正 回收该对象所占有的资源。 强制垃圾回收 •强制系统垃圾回收有如下两个方法:   –调用System类的gc()静态方法:System.gc()   –调用Runtime对象的gc()实例方法:Runtime.getRuntime().gc() finalize方法 •finalize方法有如下四个特点:   –永远不要主动调用某个对象的finalize方法,该方法应交给垃圾回收机制调用。   –finalize方法的何时被调用,是否被调用具有不确定性。不要把finalize方法当成一定会被执行的方法。   –当JVM执行去活对象的finalize方法时,可能使该对象,或系统中其他对象重新变成激活状态。   –当JVM执行finalize方法时出现了异常,垃圾回收机制不会报告异常,程序继续执行。 对象的软、弱和虚引用 •强引用(StrongReference) •软引用-软引用需要通过SoftReference类来实现,当一个对象只具有软引用时,它有可能被垃圾回收机制回 收。 •弱引用-弱引用通过WeakReference类实现,弱引用和软引用很像,但弱引用的引用级别更低。对于只有弱引 用的对象而言,当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。 •虚引用-虚引用通过PhantomReference类实现,虚应用完全类似于没有引用。虚引用对对象本身没有太大影 响,对象甚至感觉不到虚引用的存在。 修饰符的适用范围 顶层类/接口 成员属性 方法 构造器 初始化块 成员内部类 局部成员 public √ √ √ √ √ protected √ √ √ √ 包访问控制符 √ √ √ √ ○ √ ○ private √ √ √ √ abstract √ √ √ final √ √ √ √ √ static √ √ √ √ strictfp √ √ √ synchronized √ native √ transient √ volatile √ 使用JAR文件的好处 •1.安全 •2.加快下载速度 •3.压缩 •4.包封装 •5.可移植性 jar命令详解 •-c 创建新文档,-t 列出存档内容的列表, -x 展开存档中的命名文件 •-u 更新已存在的存档,-v生成详细输出到标准输出上 •-f 指定存档文件名,-m 包含 来自标文件的标明信息 •-o 只存储方式:未用ZIP压缩格式 •-m 不产生所有项的清单文件,- I 为指定的jar文件产生索引信息 •-c 改变到指定的目录, 创建可执行的JAR包 •1.使用平台相关的编译器将整个应用编译成平台相关的可执行性文件 •2.为整个应用编辑一个批处理文件 关于JAR包的技巧 •相当于一个压缩文件。 •可使用WinRAR来压缩JAR包。 •也可使用WinRAR来查看JAR包。 现在贴出代码: AutoBoxingUnboxing Primitive2String UnsignedTest WrapperClassCompare EqualTest Person OverrideEqualsRight PrintObject StringCompareTest ToStringTest NullAccessStatic Singleton Address CacheImmutaleTest FinalErrorTest FinalLocalTest FinalLocalVariableTest FinalMethodTest FinalReferenceTest FinalReplaceTest FinalVariableTest ImmutableStringTest IntegerCacheTest Person Sub extends PrivateFinalMethodTest StringJoinTest CarSpeedMeter Circle extends Shape abstract class Shape SpeedMeter Triangle 复制代码 public class AddCommand implements Command { public void process(int[] target) { int sum = 0; for (int tmp : target) { sum += tmp; } System.out.println("数组元素的总和是:" + sum); } } **************************************************** public class BetterPrinter implements Output { private String[] printData = new String[MAX_CACHE_LINE * 2]; // 用以记录当前需打印的作业数 private int dataNum = 0; public void out() { // 只要还有作业,继续打印 while (dataNum > 0) { System.out.println("高速打印机正在打印:" + printData[0]); // 把作业队列整体前移一位,并将剩下的作业数减1 System.arraycopy(printData, 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE * 2) { System.out.println("输出队列已满,添加失败"); } else { // 把打印数据添加到队列里,已保存数据的数量加1。 printData[dataNum++] = msg; } } } ************************************************ public interface Command { // 接口里定义的process()方法用于封装“处理行为” void process(int[] target); } ********************************************** public class CommandTest { public static void main(String[] args) { ProcessArray pa = new ProcessArray(); int[] target = { 3, -4, 6, 4 }; // 第一次处理数组,具体处理行为取决于PrintCommand pa.process(target, new PrintCommand()); System.out.println("------------------"); // 第二次处理数组,具体处理行为取决于AddCommand pa.process(target, new AddCommand()); } } ************************************************* public class Computer { private Output out; public Computer(Output out) { this.out = out; } // 定义一个模拟获取字符串输入的方法 public void keyIn(String msg) { out.getData(msg); } // 定义一个模拟打印的方法 public void print() { out.out(); } } ********************************************** interface interfaceA { int PROP_A = 5; void testA(); } interface interfaceB { int PROP_B = 6; void testB(); } interface interfaceC extends interfaceA, interfaceB { int PROP_C = 7; void testC(); } public class InterfaceExtendsTest { public static void main(String[] args) { System.out.println(interfaceC.PROP_A); System.out.println(interfaceC.PROP_B); System.out.println(interfaceC.PROP_C); } } ************************************************** public interface Output { // 接口里定义的成员变量只能是常量 int MAX_CACHE_LINE = 50; // 接口里定义的普通方法只能是public的抽象方法 void out(); void getData(String msg); // 在接口中定义默认方法,需要使用default修饰 default void print(String... msgs) { for (String msg : msgs) { System.out.println(msg); } } // 在接口中定义默认方法,需要使用default修饰 default void test() { System.out.println("默认的test()方法"); } // 在接口中定义类方法,需要使用static修饰 static String staticTest() { return "接口里的类方法"; } } ********************************************** public class OutputFactory { public Output getOutput() { // return new Printer(); return new BetterPrinter(); } public static void main(String[] args) { OutputFactory of = new OutputFactory(); Computer c = new Computer(of.getOutput()); c.keyIn("轻量级Java EE企业应用实战"); c.keyIn("疯狂Java讲义"); c.print(); } } *********************************************** public class OutputFieldTest { public static void main(String[] args) { // 访问另一个包中的Output接口的MAX_CACHE_LINE System.out.println(lee.Output.MAX_CACHE_LINE); // 下面语句将引起"为final变量赋值"的编译异常 // lee.Output.MAX_CACHE_LINE = 20; // 使用接口来调用类方法 System.out.println(lee.Output.staticTest()); } } ************************************************ public class PrintCommand implements Command { public void process(int[] target) { for (int tmp : target) { System.out.println("迭代输出目标数组的元素:" + tmp); } } } *********************************************** // 定义一个Product接口 interface Product { int getProduceTime(); } // 让Printer类实现Output和Product接口 public class Printer implements Output, Product { private String[] printData = new String[MAX_CACHE_LINE]; // 用以记录当前需打印的作业数 private int dataNum = 0; public void out() { // 只要还有作业,继续打印 while (dataNum > 0) { System.out.println("打印机打印:" + printData[0]); // 把作业队列整体前移一位,并将剩下的作业数减1 System.arraycopy(printData, 1, printData, 0, --dataNum); } } public void getData(String msg) { if (dataNum >= MAX_CACHE_LINE) { System.out.println("输出队列已满,添加失败"); } else { // 把打印数据添加到队列里,已保存数据的数量加1。 printData[dataNum++] = msg; } } public int getProduceTime() { return 45; } public static void main(String[] args) { // 创建一个Printer对象,当成Output使用 Output o = new Printer(); o.getData("轻量级Java EE企业应用实战"); o.getData("疯狂Java讲义"); o.out(); o.getData("疯狂Android讲义"); o.getData("疯狂Ajax讲义"); o.out(); // 调用Output接口中定义的默认方法 o.print("孙悟空", "猪八戒", "白骨精"); o.test(); // 创建一个Printer对象,当成Product使用 Product p = new Printer(); System.out.println(p.getProduceTime()); // 所有接口类型的引用变量都可直接赋给Object类型的变量 Object obj = p; } } ************************************************* public class ProcessArray { public void process(int[] target, Command cmd) { cmd.process(target); } } 复制代码 。。。。。。。。。。。。。。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值