访问权限控制
初始化
重载:相同方法名和返回类型,独一无二的参数列表
声明对象
Box b1=new Box();
Box b2=b1;
//b1和b2 指向同一个对象 bi.equals(b2)==true
一个方法调用自身:不会产生新的副本、重新分配堆栈(递归)
基本数据类型:不使用new
构造器:静态方法、类同名、无return、有参无参
this关键字:不能串行调用两个构造器
方法作用域:作用域内,变量创建;作用域终止,变量销毁
static关键字:
- 静态域(数据,全局变量)、静态方法(不能引用this和super,只能访问静态方法和静态域)、静态块(类第一次加载时执行,初始化静态域)
- 只与类关联,不与对象关联,通过类调用
初始化和清理
清理:释放new分配的内存,finalize()
方法(类的结束器)
数组初始化
-
类型[] 数组名称
int[] a Random rand=new Random(47); a=new int[rand.nextInt(20)];
-
数组初始化
-
可变参数列表
class A{} public class VarArgs{ static void printArray(Object[]args){ for(Object obj:args)print(obj);// 47 3.14 11.11 } public static void main(String[]args){ printArray(new Object[]{ new Integer(47),new Float(3.14f),new Double(11.11) }) } }
-
枚举类型
public enum Spiciness{NOT,MILD,MEDIUM,HOT,FLAMING} public class EumOrder{ public static void main(String[]args){ for(Spiciness s:Spiciness.values()){ print(s);//Not,ordinal 0... } } }
-
访问控制权限
包
-
关键字:
package
,Java源文件第一句 -
库单元:该文件内声明的所有类都属于指定的包,缺省为默认包,没有名字
-
Java可运行程序是一组.class文件,可以打包并压缩为一个jar文档
-
存储路径:层次目录,
pacakge foo.bar.baz表示env/foo/bar/baz
,需要在env目录下叫用Java编译命令 -
包的存储和查找:当前工作目录/包目录(存储和查找),CLASSPATH/包目录(查找)
package MyPack; class Balance{} class AccountBalance{} //AccountBalance.java和AccountBalance.class都在MyPack目录
-
public>protected>包权限default>private
在同一个包内除了private都差不多,不同包才有default、protected的区别
private default protected public 同一个类可见 是 是 是 是 同一个包中对子类可见 否 是 是 是 同一个包中对非子类可见 否 是 是 是 不同包中对子类可见 否 否 是 是 不同包中对非子类可见 否 否 否 是 -
类权限:
- 只能是public或default
- private构造器
- static方法
class Soup1{ private Soup1(){} public static Soup1 makSoup(){return new Soup1();} } class Soup2{ private static Soup2 ps1=new Soup2(); public static Soup2 access(){return ps1;} public void f(){} } public class Lunch{ void testPrivate(){ //!Soup1 soup=new Soup1(); } void testStatic(){Soup1 soup=Soup1.makSoup();} void testSingleton(){Soup2.access().f();} }
-
继承
关键字
-
extends:
classA extends classB
- classA子类或导出类,classB超类、父类或基类,按层分类
- 方法的扩展、方法的覆盖、super关键字
- 构造器初始化:先初始化基类
-
super:指代基类的数据或方法
super.method()
基类和导出类有相同方法Super()
基类构造器有参
-
final:适用于数据、方法、类
- 对于基本数据类型,数值恒定不变
- 永不改变的编译时常量
- 必须是基本数据类型,必须赋值
- 编译时执行包含final数据的计算式
- 对于对象,引用恒定不变
- final对象数据本身可以修改
- 数组也是一种数组
-
static+final:只占据一个不能改变的存储空间,变量名全部大写、下划线分词(类似于宏定义?)
- 空白final:被声明为final但没赋初值
- 数据被使用前必须初始化
- 一个类中的final域在不同对象中不同,但又保持恒定不变
- final参数:无法在方法中改变参数引用的对象(类似于const&)
- final方法:锁定方法,继承类无法覆盖
- private隐式指定为final,继承类不可见
-
final类:不允许被继承
- final vs static
- static:static变量本质是全局变量,不能是泛型;static方法,只能访问其他static的变量和方法,不能使用super和this;代码块仅在类被加载时加载一次;只属于类,不属于对象,通过类名访问。
- final:final变量必须初始化且无法更改(const),变量名全部大写;final方法不能被重写;final类不能被继承;final对象引用不能更改,但成员可以改(指针引用锁定?);不能同时是abstract、final,抽象类不完整。
- 对于基本数据类型,数值恒定不变
向上转型
定义:将导出类引用转化为基类引用的动作(父指针?)
初始化顺序
- 编译时
- 先初始化主类的基类的静态定义(包括静态块)
- 再初始化导出类的静态定义
- 执行主类的main方法
- 声明主类对象:
- 依次初始化主类的基类的非静态定义和构造器
- 再初始化主类的导出类的非静态定义和构造器
- 声明其他类对象:
- 依次初始化其它类的基类的静态定义、非静态定义、构造器
- 再初始化导出类的
先静态定义、再非静态定义、再构造器,变量定义初始化在任何方法调用前
先基类再导出类,区别是主类的静态定义要提到最前
class Bowl{Bowl(int mark){print("Bowl:"+marker);}}
class Cupboard{
Bowl bowl3=new Bowl(3);
static Bowl Bowl4=new Bowl(4);
static{
System.out.println("in static field");
Bowl bowl5=new Bowl(5);
}
Cupboard(){print("Cupboard");}
}
public class InitializeTest{
public statci void main(String[]args){
print("in main");
new Cupboard();
new Cupboard();
}
}
//in main
//Bowl:4
//in static field
//Bowl:5
//Bowl:3
//Cupboard
//Bowl:3
//Cupboard
class Bowl{Bowl(int mark){print("Bowl:"+marker);}}
class Cupboard{
Bowl bowl3=new Bowl(3);
static Bowl Bowl4=new Bowl(4);
static{
System.out.println("in static field");
}
Cupboard(){print("Cupboard");}
}
public class InitializeTest{
Bowl Bowl40=new Bowl(40);
static Bowl Bowl10=new Bowl(10);
static void printTest(){print("printTest");}
public statci void main(String[]args){
print("in main");
new Cupboard();
}
}
//Bowl:10
//in main
//Bowl:4
//in static field
//Bowl:3
//Cupboard
class Insect{
private int i=9;
protected int j;
Insect(){print(i);print(j);j=39;}
private static int x1=printInit("static Insect.x1");
static int printInit(String s){print(s);return 47;}
}
public class Beetle extends Insect{
private int k=printInit("Beetle.k");
public Beetle(){print(k);print(j);}
private static int x2=printInit("static Beetle.x2");
public static void main(String[]args){
print("in main");
Beetle b=new Beetle();
}
}
//static Insect.x1
//static Beetle.x2
//in main
//9 0
//Beetle.k
//47 39
Java类库和核心类库
-
以基础类库JFC(Java Foundation Class)的形式为程序员提供编程接口API;
-
类库中的类按照用途归属于不同的包中;java.lang,java.awt,javax.swing,java.io,java.util,java.net,java.applet
-
java.lang:Java最常用的包都属于该包,default包含;
-
String类,提供了字符串连接、比较、字符定位、字符串打印等处理方法。
-
StringBuffer类,提供字符串进一步的处理方法,包括子字符串处理、字符添加插入、字符替换等。
-
System类,提供对标准输入、输出设备io的读写方法,包括键盘、屏幕的in/out控制。常用的System.out.print()、System.out.println()都是该类的静态变量输出流out所提供的方法。
-
Thread类,提供Java多线程处理方法,包括线程的悬挂、睡眠、终止和运行等。
-
Math类,提供大量的数学计算方法。
-
Object类,这是Java类的祖先类,该类为所有Java类提供了调用Java垃圾回收对象方法以及基于对象线程安全的等待、唤醒方法等。
-
Throwable类,该类是Java错误、异常类的祖先类,为Java处理错误、异常提供了方法。
-
-
java.awt:提供了图形界面的创建方法,包括按钮、文本框、列表框、容器、字体、颜色和图形等元素的建立和设置。
-
javax.swing:提供100%Java编写的图形界面创建类,利用该包的类建立的界面元素可调整为各种操作系统的界面风格,支持各种操作平台的界面的开发。还提供了树形控件、标签页控件、表格控件的类。从java.awt中继承,更推荐使用。
-
java.io:
-
提供数据流方式的系统输入输出控制、文件和对象的读写串行化处理;
-
常见的类有:
BufferInputStream、BufferOutputStream、BufferedReader、BufferedWriter、DataInputStream、DataOutputStream、File、FileReader、FileWriter、FileInputStream和FileOutputStream
等
-
-
java.util:
- 提供时间日期、随机数以及列表、集合、哈希表和堆栈等创建复杂数据结构的类。
- 常见的类有:
Date、Timer、Random和LinkedList
等。
- 常见的类有:
- 提供时间日期、随机数以及列表、集合、哈希表和堆栈等创建复杂数据结构的类。
-
java.net:
- 提供网络开发的支持;
- 包括封装了Socket套接字功能的服务器Serversocket类、客户端Socket类以及访问互联网上的各种资源的URL类;
-
java.applet:
- 只有一个Applet类,用于开发或嵌入到网页上的Applet小应用程序,使网页具有更强的交互能力以及多媒体、网络功能。
-
-
Object类:位于java.lang包中,是所有其他类的超类
toString()
:对象内容作为字符串返回,对象无值,返回对象地址==
:对基本类型变量,比较值,对引用数据类型,比较地址equals()
:比较对象的内容是否相同clone()
:创建调用它的对象的重复样本getClass()
:返回对象的运行时类
多态
面向对象编程:封装、继承(向上转型,基类操作导出类)、多态(消除类型之间的耦合关系,允许一种类型表现出与其他相似类型的区别)
方法覆盖:覆盖一个方法时,子类方法的权限不能低于超类方法;私有方法不能被覆盖
class Super{public int field=0;public int getField(){return field;}}
class Sub extends Super{
public int field=1;
public int getField(){return field;}
public int getSupField(){return super.field();}
}
public class FieldAccess{
public static void main(String[]args){
Super sup=new Sub();
print(sup.field);//0
print(sup.getField());//1,调用了重写函数
Sub sub=new Sub();
print(sub.field);//1
print(sub.geteField());//1
print(sub.getSuperField());//0
}
}
前期绑定vs后期绑定
绑定:将一个方法调用同另一个方法主题关联起来
多态:后期绑定,再运行时根据对象的类型(Java)
class StaticSuper{
public static String staticGet(){return "base static";}
public String dynamicGet(){return "base dynamic";}
}
class StaticSub extends StaticSuper{
public static String staticGet(){return "derived static";}
public String dynamicGet(){return "derived dynamic";}
}
public class test{
pubic static void main(String[]args){
StaticSup sup=new StaticSub();//upcast
print(sup.staticGet());//base static
print(sup.dynamicGet());//derived dynamic
}
}
基类和导出类的upcast向上转型
- 不能覆盖的部分是基类的:域和静态方法
- 可以覆盖的部分是导出类的:非静态方法
构造器和多态
- 构造器:static方法
- 清理
接口
- 抽象类:包含一个或多个抽象方法,
abstract void f()
抽象方法只有声明没有方法体 - 接口:全都是抽象方法,默认
abstract和public
,导出类必须全部覆盖接口方法- 可以向上转型,避免创建该接口的对象
工厂模式
- 简单工厂模式,静态工厂方法模式
- 定义创建对象的接口:工厂类(java具体类),抽象产品(接口或抽象类),具体产品(实例)
内部类+持有对象
内部类
-
特殊的继承关系,类的定义在外部类的里面
class Parcell{ class Destination{ private String label; String readLable(){return label;} } public void ship(String dest){ Destination d =new Destination(dest); System.out.println(d.readLabel()); } public static void main(Sting[]args){ Parcelll p =new Parcell(); p.ship("Tasmania"); } }
-
内部类可以访问外部类定义所在的作用域中的数据,包括私有数据,可以对同一个包中的其他类进行隐藏 外部类不能访问内部类的数据
//: innerclasses/Sequence.java package innerclasses; /* Added by Eclipse.py */ // Holds a sequence of Objects. interface Selector { boolean end(); Object current(); void next(); } public class Sequence { private Object[] items; private int next = 0; public Sequence(int size) { items = new Object[size]; } public void add(Object x) { if(next < items.length) items[next++] = x; } private class SequenceSelector implements Selector { private int i = 0; public boolean end() { return i == items.length; } public Object current() { return items[i]; } public void next() { if(i < items.length) i++; } } public Selector selector() { return new SequenceSelector(); } } public static void main(String[] args) { Sequence sequence = new Sequence(10); for(int i = 0; i < 10; i++) sequence.add(Integer.toString(i)); Selector selector = sequence.selector(); while(!selector.end()) { System.out.print(selector.current() + " "); selector.next(); } } }
-
this关键字:
-
方法需要引用调用它的对象
-
在构造器中调用构造器:可以加参数,不能调用两个构造器,不能在其他方法内调用构造器
-
区分同一个名称声明的局部变量
-
this vs new
public class DotThis{ public class Inner{} public Inner inner{return new Inner();} public static void main(String[]args){ DotThis dt=new DotThis(); DotThis.Inner dti=dt.inner(); DotThis.Inner dtii=dt.new Inner(); } }
-
-
内部类对象的创建
- 必须先创建外部类对象
- 外部类的的方法:直接声明内部类对象
- 外部类对象.new 内部类对象
-
内部类的权限:无法访问私有内部类
class Parcel4{ private class PContents implements Contents{ private int i=11; public int value(){return i;} } protected class PDestination implements Destination{ private PDestination(String s){} } public Contents contents(){return new PContents();} public Destination destination(String s){return new PDestination(s);} } public class test{ public static void main(String[]args){ Parcel4 p=new Parcel4(); Contents c=p.contents(); Destination d=p.destination("test"); // --非法操作--无法访问私有类,后面有问题 // ! Parcel4.PContents pc=p.new PContents(); } }
-
内部类分类
-
局部内部类:定义在方法的作用域
- 局部内部类不能用public或private访问说明符、static声明(自动拥有方法内访问权限,方法内部创建)
- 作用域仅限定在声明局部类的块中
- 对外部世界可以完美地隐藏起来
- 只能访问外部类变量、外部方法的final已初始化的变量、外部方法的final形参(Java8之后似乎没这个final限制)
- 调用局部内部类方法:new一个对象、匿名对象
public class Parcel5{ public Destination destination(String s){ class PDestination implements Destination{ private String label; private PDestination(String whereTo){label=whereTo;} public String readLabel(){return label;} } Destination t=new PDestination(s); t.readLabel(); // new一个对象 new PDestination(s).readLabel(); // 匿名对象 return new PDestination(s); } public static void main(String[]args){ Parcel5 p=new Parcel5(); Destination d=p.destination("Tasmania"); } }
private boolean beepout; public void start(int interval,final boolean beep){ final boolean beepin=false; class TimePrinter implements ActionLinstener{ public void actionPerformed(ActionEvent event){ if(beepout){} // 外部类变量 if(beepin){} if(beep){} // 只能访问形参和外部方法final变量 } } ActionListener listener=new TimePrinter(); }
-
匿名内部类:局部内部类的一种,定义类的同时创建类对象
- 只创建这个类的一个对象,无需命名
- 用于构造对象的任何参数都要放在超类名后面的括号()内,构造器参数传递给超类superclass构造器(接口或抽象类),定义变量和方法
public class Parcel8{ public Wrapping wrapping(int x){ return new Wrapping(x){ public int value(){return super.value()*47;} } } public static void main(String[]args){ Parcel8 p =new Parcel8(); Wrapping w=p.wrapping(1); } }
- 构造器的名字必须和类名相同,匿名类不能有构造类
interface Contents{int value();} public class Parcel7{ public Contents contents(){ return new Contents{ private int i=11; public int value(){return i;} } } class MyContents implements Contents{ private int i=11; public int value(){return i;} } public static void main(String[]args){ Parcel7 p=new Parcel7(); Contents c=p.contents(); } }
- 匿名内部类使用外部类的非局部数据不要求是final变量,使用外部方法的任何数据都要求是final变量,和局部内部类相同
public class Parcel9 { // Argument must be final to use inside // anonymous inner class: int test1 = 100; public Destination destination(final String dest) { final int test2 = 300; return new Destination() { private String label = dest; private int dest1 = test1; private int dest2 = test2; public String readLabel() { return label; } }; } public static void main(String[] args) { Parcel9 p = new Parcel9(); Destination d = p.destination("Tasmania"); } }
- 匿名内部类既可以扩展类,也可以实现接口,但仅能实现一个扩展类或接口
-
嵌套类
-
静态内部类(嵌套类):
- 对象生成:new 外部类.内部类()
- 必须通过外部类
- 访问外部类数据
public class OuterClass { private static int outerVariable; public static class StaticInnerClass { public void accessOuterData() { System.out.println("Outer Variable: " + outerVariable); } } public static void main(String[] args) { // 类调用 OuterClass.StaticInnerClass inner = new OuterClass.StaticInnerClass(); inner.accessOuterData(); } }
-
非静态内部类
- 对象生成:外部类.new 内部类()
- 可以直接访问外部类的数据
public class OuterClass { private int outerVariable; public class InnerClass { public void accessOuterData() { System.out.println("Outer Variable: " + outerVariable); } } public static void main(String[] args) { OuterClass outer = new OuterClass(); // 对象调用 OuterClass.InnerClass inner = outer.new InnerClass(); inner.accessOuterData(); } }
-
嵌套内部类:接口内可放置内部类,内部类自动是public static
- 用嵌套内部做测试
public interface ClassInInterface{ void dowdy(); class Test implements ClassInInterface{ public void howdy(){} public void static main(String[]args){ new Test().howdy(); } } }
public class TestBed{ public void f(){} public static class Tester{ public static void main(String[]args){ TestBed t=new TestBed(); t.f(); } } }
-
一个内部类可以被嵌套很多层,能够透明地访问所有它所嵌入的外部类的所有成员(数据+方法)
class MNA{ private void f(){}; class A{ private void g(){}; public class B{ void h(){f();g();} } } } public class test{ public static void main(String[]args){ MNA mna=new MNA(); MNA.A a=mna.new A(); // MNA.A.B b=a.new B(); b.h(); } }
-
-
-
内部类的继承
class WithInner{ class Inner(); } public class InheritInner extends WithInner.Inner{ // ! InheritInner(){} 不会编译 InheritInner(WithInner wi){ wi.super(); } public static void main(String[]args){ WithInner wi=new WithInner(); InheritInner ii=new InheritInner(wi); } }
-
内部类的覆盖
-
内部类和外围类是两个独立的个体,不存在内部类覆盖
class Egg{ private Yolk y; protected class Yolk{ public Yolk(){print("Egg.Yolk()");} } public Egg(){ print("new Egg()"); y=new Yolk(); } } public class BigEgg extends Egg{ public class Yolk{ public Yolk(){print("BigEgg.Yolk()");} } public static void main(String[]args){ new BigEgg(); } }
-
声明主类对象,先初始化主类的基类的非静态定义和构造器,再初始化主类的
class Egg2{ protected class Yolk{ public Yolk(){print("Egg2.Yolk()");} public void f(){print("Egg2.Yolk.f()");} } private Yolk y=new Yolk(); public Egg2(){print("new Egg2()");} public void incertYolk(Yolk yy){y=yy;} public void g(){y.f();} } public class BigEgg2 extends Egg2{ public class Yolk extends Egg2.Yolk{ public Yolk(){print("BigEgg2.Yolk()");} public void f(){print("BigEgg2.Yolk.f()");} } public BigEgg2(){insertYolk(new Yolk());} public static void main(String[]args){ Egg2 e2=new BigEgg2(); e2.g(); } }
Egg2.Yolk() new Egg2() Egg2.Yolk() BigEgg2.Yolk() BigEgg2.Yolk.f() // 重写
-
持有对象
-
保存一组对象——容器类库
-
Collection:一个独立元素的序列,这些元素服从一条或多条规则
- List 处理有顺序的、可重复的对象,随机访问的线性表
新增的方法
add、addAll、get、indexOf、lastIndexOf、listIterator、remove、set、subList
-
LinkedList 经常从表中插入删除
新增
get、remove、insert
在首部和尾部,可作为stack、queue、deque没有同步
- ArrayList 元素随机访问 可变大小数组,允许包括null的所有元素 capacity,存储元素数组的大小,可自动扩容 ensureCapacity保证插入正确,没有同步
- Vector 线程安全,但效率差,几乎不用
同步的:不同线程的iterator同时使用抛出ConcurrentModificationException异常
- Stack(新增
push、pop、peek、empty、search
方法)、Queue 行为由LinkedList提供支持
- Stack(新增
-
- Set 不允许由重复的对象
- HashSet 提供最快的查询速度 无序、无下标、底层数组
- LinkedHashSet 以插入顺序保存元素
- SortSet 按照数字将元素排序,为可排序集合,默认升序 基于TreeSet实现
- TreeSet 保持元素处于排序状态,按二叉树排序 实现Comparable接口的compareTo()方法实现元素不重复 每次插入会再排序,低效率
- Queue 队列
- PriorityQueue 优先队列,构造队列时提供Comparator排序
import java.util.* public class test{ public static void main(String[]args){ Collection<Integer>c=new ArrayList<Integer>(); for(int i=0;i<10;i++)c.add(i) // 自动包装 for(Integer i:c)... } }
- List 处理有顺序的、可重复的对象,随机访问的线性表
新增的方法
-
迭代器
- Iterator(),准备好序列的第一个元素
- Next(),获得序列的下一个元素
- hasNext(),检查是否还有元素
- remove(),删除最近返回的元素
Iterator it=collection.iterators();//获得一个迭代子 while(it.hasNext()){ Object obj=it.next();//得到下一个元素 }
-
foreach和迭代器
-
Map:一组成对的“键值对”对象,允许使用键来查找值 提供对象到对象的映射
- Hashtable HashMap和HashTable的区别等同于ArrayList和Vector的区别
- HashMap
使用hash实现的Map
改变操作(增减键值对)
put、remove、clear
查询操作get、intsize、isEmpty
键值对作为集合处理keySet、values
- LinkedHashMap
- TreeMap vs HashMap Hash便于插入,Tree便于遍历 使用Hash构造,然后映射到Tree可能更快 TreeMap的元素可排序 均实现了Cloneable接口
- WeakHashMap
-
自动拆箱+泛型
泛型
-
泛型:创建一个类,使用类型作为参数(类似于C++类模板),作用于类、接口、方法
class Java_Class<K,V>或interface Java_Interface<K,V>
- 在泛型之前,使用Object类型进行多种数据类型操作
- 使用Object进行数据强制转换,基于开发者明确数据类型(比如Object转String)
- 类型不一致,编译器不报错,运行时出错
- 所以编译时需要类型安全检查,运行时强制类型转化、隐式转化(使用泛型)
- 泛型作用
- 告诉编译器每个集合接收哪些对象类型,编译器自动做类型转换
- 编译时就可知是否向集合中插入错误类型元素
- 提高程序复用性
- 创造容器,指定容器持有什么类型的对象,由编译器保证类型正确
public class test{
public class getObj<T>{ // 普通泛型,类型外部指定;复杂泛型,指定两个泛型类型
private T myObj;
public T getObj(){return myObj;}
public void setObj(T obj){myObj=obj;}
}
public void main(String args[]){
getObj<String>strObj=new getObj<String>();
strObj.setObj("string");
System.out.println(strObj.getObj());
getObj<double>douObj=new getObj<double>();
}
}
-
注意:
- 定义泛型类,在<>之间定义形式类型参数
- 实例化泛型类,指定类型参数,共两次书写
- 泛型中
<K extends Object>
中extends关键字不代表继承,是类型范围约束 - 通配符仅在声明时使用
-
无界通配符
public class test{ public class Info<T>{ ... } public void main(String args[]){ Info<String>i=new Info<String>(); fun(i); } public static void fun(info<?>temp){ System.out.println(temp); // 可以接收任意类型的泛型对象 } }
-
上界通配符
public class test{ public class Info<T>{ ... } public void main(String args[]){ Info<Integer>i1=new Info<Integer>(); //Integer泛型对象 fun(i1); Info<Float>i2=new Info<Float>(); //Float泛型对象 i2.setVar(30.1f) // 设置小数,自动装箱 fun(i2); } public static void fun(Info<? extends Number>temp){ System.out.println(temp); // 只能接收Number及其子类 } }
-
下界通配符
public class test{ public class Info<T>{ ... } public void main(String args[]){ Info<String>i1=new Info<String>(); //Integer泛型对象 fun(i1); Info<Object>i2=new Info<Object>(); //Float泛型对象 i2.setVar(new Object()`) // 设置小数,自动装箱 fun(i2); } public static void fun(Info<? super String>temp){ System.out.println(temp); // 只能接收String或Object类型的泛型 //只能接收类和超类 } }
-
泛型不能向上转型
public class test{ public class Info<T>{ ... } public void main(String args[]){ Info<String>i1=new Info<String>(); Info<Object>i2=null; i2=i1;// 错误,i1!=i2 泛型不能向上转型 } }
-
Java泛型接口:使用泛型接口还是实类型接口
interface Info<T>{ // 在接口上定义泛型 public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型 } class InfoImpl<T> implements Info<T>{ // 定义泛型接口的子类 private T var ; // 定义属性 public InfoImpl(T var){ // 通过构造方法设置属性内容 this.setVar(var) ; } public void setVar(T var){ this.var = var ; } public T getVar(){ return this.var ; } }; public class GenericsDemo24{ public static void main(String arsg[]){ Info< String> i = null; // 声明接口对象,接口需要类型参数 i = new InfoImpl< String>("汤姆") ; // 通过子类实例化对象 System.out.println("内容:" + i.getVar()) ; } }; }
interface Info< T>{ // 在接口上定义泛型 public T getVar() ; // 定义抽象方法,抽象方法的返回值就是泛型类型 } class InfoImpl implements Info< String>{ // 定义泛型接口的子类 private String var ; // 定义属性 public InfoImpl(String var){ // 通过构造方法设置属性内容 this.setVar(var) ; } public void setVar(String var){ this.var = var ; } public T getVar(){ return this.var ; } }; public class GenericsDemo25{ public static void main(String args[]){ Info i = null; // 声明接口对象,接口可以不用类型参数 i = new InfoImpl ("汤姆") ; // 通过子类实例化对象 System.out.println("内容:" + i.getVar()) ; } };
-
Java泛型方法
class Demo{ public <T> T fun(T t){ // 可以接收任意类型的数据 return t ; // 直接把参数返回 } }; public class GenericsDemo26{ public static void main(String args[]){ Demo d = new Demo() ; // 实例化Demo对象,不用类型参数 String str = d.fun("汤姆") ; // 传递字符串 int i = d.fun(30) ; // 传递数字,自动装箱 System.out.println(str) ; // 输出内容 System.out.println(i) ; // 输出内容 } };
-
使用泛型方法返回泛型实例
class Info< T extends Number>{ // 指定上限,只能是数字类型 private T var ; // 此类型由外部决定 public T getVar(){ return this.var ; } public void setVar(T var){ this.var = var ; } public String toString(){ // 覆写Object类中的toString()方法 return this.var.toString() ; } }; public class GenericsDemo27{ public static void main(String args[]){ Info< Integer> i = fun(30) ; System.out.println(i.getVar()) ; } public static < T extends Number> Info< T> fun(T param){ //方法中传入或返回的泛型类型由调用方法时所设置的参数类型决定 !!! Info< T> temp = new Info< T>() ; // 根据传入的数据类型实例化 Info temp.setVar(param) ; // 将传递的内容设置到Info对象的var属性之中 return temp ; // 返回实例化对象 } };
-
泛型数组
public class GenericsDemo30{ public static void main(String args[]){ Integer i[] = fun1(1,2,3,4,5,6) ; // 返回泛型数组 fun2(i) ; } public static < T> T[] fun1(T...arg){ // 接收可变参数!!! return arg ; // 返回泛型数组 } public static < T> void fun2(T param[]){ // 输出 System.out.print("接收泛型数组:") ; for(T t:param){ System.out.print(t + "、") ; } } }
-
Java泛型的嵌套设置:比如
<List<String>>
class Info<T,V>{ // 接收两个泛型类型 private T var ; private V value ; public Info(T var,V value){ this.setVar(var) ; this.setValue(value) ; } public void setVar(T var){ this.var = var ; } public void setValue(V value){ this.value = value ; } public T getVar(){ return this.var ; } public V getValue(){ return this.value ; } }; class Demo< S>{ private S info ; public Demo(S info){ this.setInfo(info) ; } public void setInfo(S info){ this.info = info ; } public S getInfo(){ return this.info ; } }; public class GenericsDemo31{ public static void main(String args[]){ Demo< Info< String,Integer>> d = null ; // 将Info作为Demo的泛型类型 Info< String,Integer> i = null ; // Info指定两个泛型类型 i = new Info< String,Integer>("汤姆",30) ; // 实例化Info对象 d = new Demo< Info < String,Integer>>(i) ; // 在Demo类中设置Info类的对象 System.out.println(“内容一: " + d.getInfo().getVar()) ; System.out.println("内容二: " + d.getInfo().getValue()) ; } };
-
Java的泛型使用了”消磁“,也就是说如果希望表示”任何类型”,Java会将这个任何类型转化为Object 如果需要在泛型方法中使用其他方法method,需要定义包含了method方法的接口interface,并且限制只能传入这个接口
interface Speaks{void talk();} class Dog implements Speaks{public void talk();} class Cat implements Speaks{public void talk();} class Comment{ public static <T> void speak(T speaker){ speaker.talk(); } } public test{ public static void main(String[]args){ Dog d=new Dog();Cat c=new Cat(); Comment.speak(d);Comment.speak(c); } }
-
Java的泛型只是对Object类型的一个泛化而已,解决了容器类之间的自动转型 Java中的泛型是真正的自动转型,真正的泛型,是隐式类型
自动拆箱
-
打包基本数据类型:Long、Integer、Boolean就是Wrapper类
-
目的:将基本数据类型当作对象操作
-
Char='x';Character ch='x';Character ch=new Character('x');Char c=ch
-
-
自动装箱:java.lang.Number类
Number num=3.14f
自动拆箱:将对象的基本数据形态从对象中自动取出int fooInt=new Integer(10);
-
运算时也能自动装箱和拆箱
-
编译器在编译时根据语法,决定装箱或拆箱
-
public class test{ public static void main(String[]args){ Integer i1=20;Integer i2=20; System.out.println(i1==i2); // true Integer i3=200;Integer i4=200; System.out.println(i3==i4); // false } }
- -128~127:装箱为Integer对象后,会在内存中被重用,i1和i2被拷贝至同一个对象
- 超过上述范围:不会在内存中被重用
-
数组、内部类、父类子类 、重载、红字