注意事项:
同一个包中不能有一样的类名的类,不然编译会出现错误。
(二)单例类(Singleton)
1、把构造器用private隐藏。
2、用static创建一个自定义只允许创建一个对象实例的静态方法(这样即使还没创建对象,就可以由类调用进行检查是否已经存在实例了并进行判断)。
例如:
public class Singleton { private static Singleton instance;//使用类变量来缓存曾经创建的实例; //对构造器用private进行修饰; private Singleton(){} //提供一个静态方法,用于返回Singleton实例,所以它的返回对象类型就是Singleton; //该方法加入自定义控制,保证只产生一个对象; public static Singleton getInstabce(){ if(instance==null) { instance = new Singleton(); } return instance; } public static void main(String[] args) { //创建对象不同构造器; //只通过自定义方法创建对象实例; /*Singleton s1=new Singleton(); Singleton s2=new Singleton(); System.out.println("s1==s2:"+(s1==s2));*/ //这样创建出来输出false; //getInstance()被定义为静态方法,在程序加载字节码时不用创建实例,可以由类调用 Singleton s1= Singleton.getInstabce(); Singleton s2=Singleton.getInstabce(); System.out.println("s1==s2:"+(s1==s2));//输出true;
(三)匿名内部类及Lambda表达式
1、匿名内部类(实现接口/继承父类):
看似直接定义一个接口的对象(实际接口是没有实例对象的),实际可以认为是在定义另一个实现该接口(父类)的一个类的实例,并对接口中的抽象方法等进行实现。
(1)不能是抽象类(里面的方法等必须是已实现的)
(2)不能定义构造器,因为没有匿名内部类的类名。
(3)可以定义初始化块。可以在初始化块完成构造器里面需要完成的任务。
2、Lambda表达式(参考:http://www.cnblogs.com/CarpenterLee/p/6507161.html):
Lambda表达式中形参列表是对应的接口中抽象方法的形参。
其中一个main函数中可以存在对应多个函数接口的Lambda表达式:
//存在一个或者多个函数接口时的在main()函数的Lambda表达式示例 interface Converter{ Integer converter(String from); } //////////////////////////////// interface Mytest1{ String test(String a,int b,int c); } public class Myinterface { public static void main(String []args){ //Converter converter1=(from)->Integer.valueOf(from); //Converter converter1=Integer::valueOf; //Converter converter1=from->"you".indexOf(from); Converter converter1="you"::indexOf; Integer val=converter1.converter("u"); System.out.println(val); ///////////////////////////////////
//对应的参数可以要么全部加上参数类型,要么全部不加;
Mytest mt=(String a,int b,int c)->a.substring(b,c);Mytest1 mt=( a , b , c)->a.substring(b ,c) ; //Mytest mt=String::substring; String str=mt.test( "jana i love you" , 2 , 9) ; System. out.println(str) ; }}
其中匿名内部类及Lambda表达式的区别:
1、匿名内部类可为任意接口创建实例——不管接口含有多少个抽象方法。
Lambda表达式只能为函数式接口创建实例(里面只含有唯一一个抽象方法,但是可以有多个默认方法).
2、匿名内部类可以为普通类、抽象类创建实例,但是,Lambda·表达式只能为函数式接口创建。
3、匿名内部类实现的抽象方法允许调用接口中定义的默认方法,但是Lambda表达式不允许这样调用。
二、权限与修饰符(public、protect、private、final)
1、一般被定义为私有的属性(private)需要设置其setter(),getter()方法,方便封装之后被使用。
2、"构造器没有返回值为什么不可以用void声明?"
答:实际类的构造器是有返回值的,当使用new关键字调用构造器时,构造器返回该类的实例,可把该实例当做返回值。必须注意,不要在构造器中显示使用return来返回当前类的对象,因为构造器的返回值是隐式的。
3、final修饰的成员变量必须由程序员显式的指定初始值(系统不会对final成员进行隐式初始化),当该变量被赋予初始值时,就不能再被重新赋值。普通方法不能为final修饰的变量赋值。
(1)final修饰基本类型变量
①final修饰类变量(final static ):该类变量可以在声明的时候指定【类初始化时分配默认值(不推荐,最好显示初始化)】,静态语句块中初始化(不能在普通初始化块初始化,因为类变量在类初始阶段就已经被初始化了,之后普通初始化块就不能再对其赋值)。只在这二者之一初始化。
②final修饰的成员变量(实例变量):可以在定义时初始化,普通(必须为非静态)初始化块初始化(实例变量不能在静态初始化块制定初始值,因为静态初始化块是静态成员,不可访问实例变量),构造器中初始化,只在这三者之一。普通方法不能为final修饰的成员变量赋值。
例如:
public class FinalVariableTest { //定义成员变量指定默认值,合法; final int a=6; final String str;//可在构造器、普通初始化块初始化; final int c;//可在构造器、普通初始化块初始化; final static double d;//静态初始化块; // final char ch; 若哪儿都没有初始化是不合法的; //普通初始化块 { str="Hello"; //不能重新为a赋值; //a=9; } //静态初始化块 static { d=5.6;//为类变量初始赋值; } public FinalVariableTest(){ c=5; } public void changeFinal(){ //普通方法不能为final修饰的变量赋值; //d=2; //ch='a'; } public static void main(String[] args){ FinalVariableTest ft=new FinalVariableTest(); System.out.println(ft.a); System.out.println(ft.c); System.out.println(ft.d); } }//输出为 6 5 5.6
(2)final修饰引用类型变量:只保证引用类型变量所引用的地址不改变,即一直引用同一个对象,但这个对象内部内容可以改变。
三、继承
1、
四、数据类型
1、Java中有5种成员:初始化块,成员变量,方法,构造器,内部类(包括接口、枚举)。其中,创建Java对象时,系统总是隐式先调用该类的定义的初始化块,根据初始化块所在位置从上到下执行,在构造器之前执行。因为它没有名字,表示,所以无法通过类、对象来调用初始化块,初始化块只能用static修饰。
2、基本类型与引用类型的区别:
(1)基本类型:它的值就是一个数字,一个字符或一个布尔值。
(2)引用类型:是一个对象类型,值是什么呢?它的值是指向内存空间的引用,就是地址,所指向的内存中保存着变量所表示的一个值或一组值。除了在函数传值的时候是"引用传递",在任何用"="向对象变量赋值的时候都是"引用传递"。
例如:
int a;
a=250; //声明变量a的同时,系统给a分配了空间。
引用类型就不是了,只给变量分配了引用空间,数据空间没有分配,因为谁都不知道数据是什么,整数,字符?我们看一个错误的例子:
MyDate today;
today.day = 4; //发生错误,因为today对象的数据空间未分配。
那我们怎么给它赋值?引用类型变量在声明后必须通过实例化开辟数据空间,才能对变量所指向的对象进行访问。举个例子:
MyDate today; //将变量分配一个保存引用的空间
today = new MyDate(); //这句话是2步,首先执行new MyDate(),给today变量开辟数据空间,然后再执行赋值操作
//引用变量赋值
MyDate a,b; //在内存开辟两个引用空间
a = new MyDate(); //开辟MyDate对象的数据空间,并把该空间的首地址赋给a
b = a; //将a存储空间中的地址写到b的存储空间中
如下图示
3、包装类
基本类型:byte、short、int、long、char、float、double、boolean
包装类:Byte、Short、Integer、Long、Character、Float、Double、Boolean
注意:虽然包装类型的变量是引用数据类型,但包装类的实例可以与数值类型进行比较,直接去除包装示例所包装的数值进行比较,例如:
Integer a=new Integer(6); //输出true ; System.out.println("6的包装类实例是否大于5.0"+(a>5.0));
但是和下例相对比:
原因:这与Java的Integer的设计有关,系统把一个-128~127之间的整数自动装箱成Integer实例,并放入一个名为cache的数组中缓存起来。所以只要是实例-128~127之间的整数就会在同一个空间中,地址相等,超出范围就重新创建shil
//输出true Integer a=2;//通过自动装箱,允许把基本类型赋值给包装类实例; Integer c=2; System.out.println("比较2个包装类实例是否相等"+(a==c)); //输出false Integer d=128; Integer e=128; System.out.println("比较2个包装类实例是否相等"+(d==e));
但是,因为包装类的实例实际上是引用类型,只有两个包装类引用同一个对象时才会返回ture。例如:
//输出false System.out.println("比较2个包装类实例是否相等"+(new Integer(2)==new Integer(2)));
同下例,因为利用了关键字new创建了不同的内存空间:
//输出false Integer a=new Integer (2); Integer c=new Integer (2); System.out.println("比较2个包装类实例是否相等"+(a==c));4、 String(final)
①
Example:
String s1 = "abc";
String s2 = "abc";
System.out.print(s1==s2);
运行结果是:true
因为,String s = "abc"这种形式可以看做我们声明了一个值为”abc”的字符串对象引用变量,由于String类是final的,所以事实上,可以看做是声明了一个字符串引用常量, 存放在常量池中(栈中)。如果是使用关键字new这种形式声明出的,则是在程序运行期被动态创建,存放在堆中。
String s = “abc”的工作过程可以分为以下几个步骤:
(1)定义了一个名为"s"的String类型的引用。
(2)检查在常量池中是否存在值为"abc"的字符串对象;
(3)如果不存在,则在常量池(字符串池)创建存储进一个值为"abc"的字符串对象。如果已经存在,则跳过这一步工作。
(4)将对象引用s指向字符串池当中的”abc“对象。
String s = new String(”abc“)的步骤则为:
(1)定义了一个名为"s"的String类型的引用。
(2)检查在常量池中是否存在值为"abc"的字符串对象;
(3)如果不存在,则在常量池(字符串池)存储进一个值为"abc"的字符串对象。如果已经存在,则跳过这一步工作。
(4)在堆中创建存储一个”abc“字符串对象。
(5)将对象引用指向堆中的对象。
这也就是为什么有道面试题:String s = new String(“xyz”);产生几个对象?的答案是:一个或两个的原因。因为如果常量池中原来没有”xyz”,就是两个。
②
如果需要把基本类型变量→字符串
(1)可将基本类型变量与“”进行连接。例如:
//intstr的值为"5";
String intstr=5+""
(2)利用valueOf()方法把基本类型转换成字符串,例如:
//把float变量转换成String变量;
String ftstr =String.valueOf(2.34764);
System.out.println(ftstr);
而字符串转成基本类型则可使用包装类提供的静态方法parseXxx(String s)。
eg: parseInt(),parseFloat().....
5、很多语言都不允许通过独享访问类变量,对象只能访问实例变量,类变量必须通过类来访问。(其实主要是实例变量和类变量两大类)
(1)类变量:
①也叫静态变量,在类中以static关键字声明,但必须在方法构造方法和语句块之外。
②静态变量除了被声明为常量外很少使用。常量是指声明为public/private,final和static类型的变量,很少单独使用static声明变量。
③默认值和实例变量相似。数值型变量默认值是0,布尔型默认值是false,引用类型默认值是null。
④可通过实例对象访问,也可通过类来访问,即使某个实例是null,null也可以访问它所属的类成员.
(2)实例变量:
①“实例变量”,在实体类或数据类中被称为“属性”或“字段”,声明在一个类中,但在方法、构造方法和语句块之外。实例变量在对象创建的时候创建,在对象被销毁的时候销毁。
②实例变量的值应该至少被一个方法、构造方法或者语句块引用,使得外部能够通过这些方式获取实例变量信息。
③实例变量对于类中的方法、构造方法或者语句块是可见的。一般情况下应该把实例变量设为私有。通过使用访问修饰符可以使实例变量对子类可见。
④实例变量具有默认值。数值型变量的默认值是0,布尔型变量的默认值是false,引用类型变量的默认值是null。变量的值可以在声明时指定,也可以在构造方法中指定。
(3)成员变量:
①类中的属性,独立于方法之外,与实例变量重叠,有些类变量也是成员变量。
(4)局部变量:
①类的方法、构造器中的变量,是被局部使用的。
例1:
public class Variable{ static int allClicks=0;//类变量 String str="hello world";//实例变量、成员变量 public void method(){ int i =0;//局部变量 int a;//局部变量 } }
例2:
public class StaticTest { private static int staticInt = 2; private int random = 2; public StaticTest() { staticInt++; random++; System.out.println("staticInt = "+staticInt+" random = "+random); } public static void main(String[] args) { StaticTest test = new StaticTest(); StaticTest test2 = new StaticTest(); } }
//运行结果: //staticInt = 3 random = 3 //staticInt = 4 random = 3//每次创建对象重新调用全新的构造器,重新加1例3:
public class Temp { static int t; //类变量 public static void main(String args[]){ System.out.println(t); //打印类变量 int t = 1; //局部变量 System.out.println(t); //打印局部变量 Temp a = new Temp(); //创建实例 System.out.println(a.t); //通过实例访问实例变量 } } //结果为:0 1 0
四、集合
1、Stream
参考链接:
http://www.cnblogs.com/CarpenterLee/p/6545321.html
http://www.cnblogs.com/CarpenterLee/p/6550212.html
五、IO
1、问题:这个对象不是文件吗?为什么还要调用其他方法再次创建文件。
答:File类实例化,比如 File f=new File("E:/file_ceshi/02.rmvb");只是指向了这个02.rmvb文件,如果不创建02.rmvb,此文件是不存在的。因为代码只是声明不是运行,否则会出错。