@w460461339
2016-11-16T07:02:17.000000Z
字数 6557
阅读 822
Java基础
在纠结了许久之后,还是选择将Java作为自己的第一语言,C++还是仅仅用作毕设好了。从实际情况出发, Java会更加适合我这样半路出发的人一些。
在之前已经刷过翁凯的Java基础和Java进阶了,只是之后没有进一步学习,忘了许多内容。这两天将之前学的知识重新捡起来,作为自己今后摩天大楼的基石。
基本的操作和C以及C++相差不大,毕竟从语言上来说,Java语言源自于C以及C++。需要知道一点,Java有八大基本类型:short,int,long,float,double,char,boolean,byte以及对应的包裹类型:Short,Integer,Lont,Float,Double,Character,Boolean,Byte.另外,常用的String是一个类,这点要与包裹类型区分开来。
还有一个需要习惯的地方是,范围for循环中,不能再用C++里面的auto去定义循环参数了,需要指明所需遍历的容器中所存的参数类型。
今天所学的面向对象的内容主要有:类,对象交互,对象容器以及继承。
目前个人感觉而言,Java中所有的代码都是基于类的,包括main。这一点就比C++更近一层,所以个人感觉也更加面向对象一些。C++的特性可以概括为重载,封装,继承以及多态。这一块中主要讲的是封装。即类中的成员变量,除非是有很充分的理由,不然一般是设为private的,即其他类是无法访问的。注意这里,封装是针对类而言,而非对象的。请看下列例子:
class DVD{
private DVD dvd=new DVD();
private int number=0;
public void print_Number(){
System.out.println(dvd.number)//此时,是可以利用‘.’运算符
//去访问dvd中private变量number的
}
}
另外,类中有一类特殊的函数,构造函数。它是为了帮助用户在创建对象时将类中的一些成员变量给初始化所用的。
class DVD{
private int number;
private boolean gotIt;
private String name;
public DVD(){//无参构造函数
}
public DVD(String name,int number){//函数重载
this.number=number;//由于存在同名变量,利用‘this’+‘.’
this.name=name;//去访问当前对象的成员变量,以抵消就近原则。
}
}
这里的话,除了前面所说的封装属性之外,还提到了Eclipse的一些文件保存机制。比如利用文件夹来保存文件等等。另外很重要的一点是类变量。其实类变量直译应该是静态成员函数,比如:
class DVD{
private DVD dvd=new DVD();
private static String artist="Avril";
…………
}
其中的artist就是类变量。类变量与一般的成员变量不同的是,它自类被创建出来之后就一直存在,而非与成员变量一样,要等类的对象创建出来之后才会存在。换句话说,对于成员变量,每个对象中的成员变量都是不同的。但是类变量是大家共有的,只有一个。同理,类函数也是一样的,比如为了调试类,创建的:
public static int main(String[] arg){
}
它是一个类函数,对于每一个对象来说,都是相同的。此外,需要注意,静态方法(函数)只能访问静态成员变量——换句话说,类函数只能访问类变量,不可以访问非类变量。
这里先说三种程序提供的容器:ArrayList< Type >,HashSet< Type >以及HashMap< TypeK,TypeV >。
ArrayList< Type >其实C++里面的vector啦,程序帮你写好了的堆栈,里面要存什么类型都由你自己决定。需要注意的是,它是一个对象容器,所以在<>里面的应该是类或者包裹类的名字。因此,比如你想创建一个村int的ArrayList,你应该用它对应的包裹类名字创建:
ArrayList<Integer> iArray = new ArrayList<Integer>();
//在HashSet以及HashMap中同理
在ArrayList中,利用add()函数添加元素,将待存储元素从0号位置顺序向后排放的。它还有一些操作,这些操作可以通过‘.’运算符来查看以及获得。
HashSet< Type >其实就是数学里面的集合。即,存储在其中元素是无序的,并且不存在相同元素(若输入了相同元素,会自动帮你删了只剩一个)。其中,也是利用.add()添加元素,其他操作请用.运算符。
HashMap< TypeKey,TypeValue >在我理解就是graceful一些的switch case。即一个Key对应一个Value。有几点需要注意的, 它的Key是存在一个Set中的,因此不能存在有相同的Key。若输入的相同的Key,后输入的Value会覆盖掉前面的Value。另外,由于Key是存储在Set中的,因此其中HashMap中的元素也是无序的。Tips,遍历以及获得大小的办法:
HashMap<Integer,String> Coin = new HashMap<Integere,String>();
Coin.put(1,"yi mao");//和其他两种容器不同,这里是用.put添加元素
Coin.put(5,"wu,mao");
Coin.put(10,"yi kuai");
int sizeofCoin=0;
sizeofCoin=Coin.keyset().size();//通过这样来获得元素数量
for(Integer i:Coin.keyset()){//用这种办法来遍历HashMap。
System.out.println(Coin.get(i));
}
说完了这三个容器,来说一说对象数组。我们知道,创建了一个对象之后,那个对象的名字其实是对象的管理者,而非所有者。这一点使得由它构成的数组与由基本类型构成的数组有所不同。
int[] iArray=new int[10];
for(int i:iArray){
i=2;//若我们通过这种办法想把iArray中的元素全部改为2,是做不到的。
//因为每次i都是从iArray中得到了一个值。
}
class DVD{
int number;
}
DVD[] dvd=new DVD[10];//注意,此时并没有创建对象,只是创建了10个格子
for(int i=0;i<dvd.length;i++){
dvd[i]=new DVD();
dvd[i].number=10;
}
for(DVD v:dvd){
v.number=20;//这样就可以将每个dvd[i]对象的number改为20。
}
这里需要说一下的是,虽然String也是类,但由于String固有的不可变性质,导致其并不能通过这样的方式改变。但是,如果将String类型放在另一个类中,通过这个类去修改,则是可以修改的。
class DVD{
public String name="hello";
}
public static void maiN(String arg[]){
String str="aloha";
System.out.println(str)\\输出aloha
//这里可以理解为String的确拥有了这个“值”
//然后把这个值又传递给了changestr的形参
//然后形参的一切操作与“我”无关
changestr(str);
System.out.println(str)\\输出aloha.
str="lalala";
System.out.println(str)\\输出lalala
DVD dvd= new DVD();
System.out.println(dvd.name)\\输出hello
dvd.name="world"
System.out.println(dvd.name)\\输出world
change(dvd);
System.out.println(dvd.name)\\输出lolo
}
public static void changestr(String str){
str="haha";
}
public static void change(DVD dvd){
dvd.name="lololo"
}
继承关键字extends,从字面意思,扩展上也很好理解,即子类不仅包含全部的父类,也有子类所独有的东西,故为扩展。
public class DVD extends Item{
//这就表明DVD这个类继承了Item这个类
}
父类中的变量有很多访问属性:public,protected,不写(即friendly)以及private。子类是将父类所有的成员变量以及成员函数都继承了,只是能不能访问到这些变量或者函数,就看其访问属性了:
作用域 | 当前类 | 同一package | 子孙类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
friendly(就是不写) | √ | √ | × | × |
private | √ | × | × | × |
(对于不能访问的,只要符合一点就不能访问;比如是子孙类,但在其他包,那么当前类的protected对象对于其子孙类而言即不可访问)
这里有一点说一下,对于friendly,如果子孙类和父类不在一个包里面,那么父类中的friendly对于子孙类就是不可访问的,但如果子孙类和父类在同一个包里面,那么父类中的friendly对子孙类就是可以访问的了。
由于子类将父类中所有的变量都继承了,所以在初始化子类自己的成员变量之前,需要将父类先构造出来,并完成初始化。下面函数中的1,2,3表示初始化的先后顺序:
public class Item{
private String title;
public int number;
public Item(){
title="blank";
}
public Item(String title){
this.title=title;//1.1将从子类中收到的title赋给父类中的title。
this.number=10;
}
}
class DVD extends Item{
//0.0 最先完成的,在类写出来的时候就有了;比类的实例还要早创建
private static String identify="330……";
private String artist;
private boolean gotIt=false; //2、完成定义初始化
private int number;
public DVD(){
}
public DVD(String title,String artist,int number){
//1.0 super表示父类,super(title)此时表示调用父类含参数String类型的构造函数
//不加参数,就表示调用父类的无参构造
super(title);
this.artist=artist;//3、完成剩下的初始化
this.number=number;//就近原则,哪怕父类中的number是public,而子类中也有number,故仅调用子类中的number。
}
}
this在类中指向该对象,而super则指向父类(对象)。
public class Item{
private int number;
public String name=“Item”;
}
class DVD extents Item{
private String name=“DVD”;
public void print(){
System.out.println(name)//输出的是DVD
System.out.println(this.name)//输出的是DVD
System.out.println(super.name)//输出的是Item
System.out.println(super.number)//不能访问,报错。
}
}
当子类中出现和父类中相同名称的方法时,子类中的方法就将父类中的方法覆盖了。一般是在需要对父类中的方法修改时用覆盖。这里需要注意,如果要实现覆盖,子类中的方法必须要和父类中的方法 返回值,名称,参数列表全部一样,而访问属性不能降低(public>protected>不写>private),不然就不是覆盖
public class Item{
private int number;
public void print(){
System.out.println("Hello");
}
}
class DVD{
private String name=“DVD”;
public void print(){//实现对父类中print函数的覆盖
System.out.println(name)//输出的是DVD
System.out.println(this.name)//输出的是DVD
System.out.println(super.name)//输出的是Item
System.out.println(super.number)//不能访问,报错。
}
}
实现覆盖的过程中,需要注意以下几点:
1.仅当类与类之间存在关系时才产生覆盖。
2.子类覆盖父类时必须要保证,子类方法的权限必须大于等于父类方法权限可以实现继承,否则编译失败。
3.不能将非静态方法覆盖为静态方法,也不能覆盖静态方法。
此时在父类中一些原来被封装好的成员,可能会因为继承而打破了封装性,此时就需要利用关键字 final 来处理类中的成员变量以及成员函数:
final特点:
1:这个关键字是一个修饰符,可以修饰类,方法,变量。
2:被final修饰的类是一个最终类,不可以被继承。
3:被final修饰的方法是一个最终方法,不可以被覆盖。
4:被final修饰的变量是一个常量,只能赋值一次。
Object是所有类,包括用户自定义类的根类——就是所有类的爸爸。它其中有这么几个有用的方法:
boolean equals(Object obj):
用于比较两个对象是否相等,其实内部比较的就是两个对象地址。
而根据对象的属性不同,判断对象是否相同的具体内容也不一样。所以在定义类时,一般都会复写equals方法,建立本类特有的判断对象是否相同的依据。
public boolean equals(Object obj){
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.age == p.age;
}
2,String toString():将对象变成字符串;默认返回的格式:
类名@哈希值 = getClass().getName() + '@' + Integer.toHexString(hashCode())
为了对象对应的字符串内容有意义,可以通过覆盖该方法,建立该类对象自己特有的字符串表现形式。
public String toString(){
return "person : "+age;
}
3,Class getClass():获取任意对象运行时的所属字节码文件对象。
package Cell
class Animal{
}
public static void main(String args[]){
Animal animal = new Animal();
System.out.println(animal.getClass())
//会输出 class Cell.Animal;即输出格式为:class +类的全名。
}
4,int hashCode():返回该对象的哈希码值。支持此方法是为了提高哈希表的性能。
通常equals,toString,hashCode,在应用中都会被复写,建立具体对象的特有的内容。