黑马程序员-----Java基础-----Java关键字、抽象类、方法重载、封装

来源:互联网 发布:查理一世 知乎 编辑:程序博客网 时间:2024/05/23 21:43

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

黑马程序员-Java关键字、抽象类、方法重载、封装


super(父类,超类)
super关键字用于引用使用该关键字的类的超类。
作为独立语句出现的 super 表示调用超类的构造方法。
super.<methodName>()表示调用超类的方法。
只有在如下情况中才需要采用这种用法:要调用在该类中被重写的方法,以便指定应当调用在超类中的该方法。

class A{  public void a(){}}class B extend A{  void foo(){    super.a();  //这里就是执行父类的a方法  }}


 
this
当引用可能不明确时,可以使用 this 关键字来引用当前的实例。
this的用法只表示当前类的属性方法,只能在自己的类使用.
this关键字是一个对象的默认引用,this关键字总是指向调用该方法的对象。 根据this出现的位置不同,this作为对象的默认引用有两种情形:
1.构造器中引用该构造器执行初始化的对象。
2.在方法中引用调用该方法的对象。

this可以代表任何对象,当this出现在某个方法中,它所代表的对象时不确信的,但它的类型是确定的,它所代表的对象只能是当前的类,只有当这个方法被调用的时候,它所代表的对象才被确定下来:谁在调用这个方法,this就代表谁。
大部分时候,一个方法访问相同实例的其他方法,属性时加不加this前缀的效果是完全一样。
对于static修饰的方法而言,则可以使用类来直接调用此方法,如果在static修饰的方法中使用this关键字,则这个关键字就无法指向合适的对象,所以,static修饰方法中不能使用this引用。由于static修饰的方法不能使用this引用,所以static修饰的方法不能访问不使用的static修饰的普通成员。
大部分时候,普通方法访问其他方法,属性时无须使用this前缀,但如果方法里有个变量和属性同名时,但程序又需要在该方法里访问这个被覆盖的属性,则必须使用this前缀。除此之外,this引用也可以用于构造器中作为默认引用,由于构造器是直接使用new关键字来调用,而不是使用对象来调用,所以this在构造器中引用的时该构造器进行初始化的对象
例:

public class ThisInConstructor{ int foo; public ThisInConstructor() {  int foo=0;  this.foo=1; } public static void main(String[] args) {  System.out.println(new ThisInConstructor().foo); } }例2: public class ThisInConstructor { int foo; public ThisInConstructor() {  this.foo=1;  int foo=0; } public static void main(String[] args){System.out.println(new ThisInConstructor().foo);   } }

两个程序运行后都得到foo的值为1。 这意味着该构造器返回的所有对象的foo属性都是1。  当this作为的默认引用使用时,程序可以像访问普通引用变量一样来访问这个this的引用,甚至可以把this当成普通方法的返回值


static特点:
1,修饰属性、方法及代码块;
2,修饰的属性和方法称为类属性和类方法;
3,static修饰的属性和方法可通过类名和对象名访问,若不用static修饰,只能通过对
   象名访问;
4,静态随着类的加载而加载。而且优先于对象存在。


静态方法:

通常,在一个类中定义一个方法为static,那就是说,无需本类的对象即可调用此方法
声明为static的方法有以下几条限制:
·它们仅能调用其他的static 方法。
·它们只能访问static数据。
·它们不能以任何方式引用this 或super。

class Simple {staticvoid go() {System.out.println("Welcome");}}publicclass Cal {publicstaticvoid main(String[] args) {Simple.go();}}

调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说,静态方法常常为应用程序中的其它类提供一些实用工具所用,在Java的类库中大量的静态方法正是出于此目的而定义的。


静态变量
声明为static的变量实质上就是全局变量。当声明一个对象时,并不产生static变量的拷贝,而是该类所有的实例变量共用同一个static变量。静态变量与静态方法类似。所有此类实例共享此静态变量,也就是说在类装载时,只分配一块存储空间,所有此类的对象都可以操控此块存储空间,当然对于final则另当别论了

class Value {staticintc = 0;staticvoid inc() {c++;}}publicclass Count2 {publicstaticvoid prt(String s) {System.out.print(s);}publicstaticvoid main(String[] args) {Value v1, v2;v1 = new Value();v2 = new Value();prt("v1.c=" + v1.c + " v2.c=" + v2.c);v1.inc();prt(" v1.c=" + v1.c + " v2.c=" + v2.c);}}
结果为:v1.c=0 v2.c=0 v1.c=1 v2.c=1
由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。


值得探讨的是静态变量的初始化问题。
如果你需要通过计算来初始化你的static变量,你可以声明一个static块,Static 块仅在该类被加载时执行一次。下面的例子显示的类有一个static方法,一些static变量,以及一个static 初始化块:

class Value3 {staticintc = 0;Value3() {c = 15;}Value3(int i) {c = i;}staticvoid inc() {c++;}}publicclass Count {publicstaticvoid prt(String s) {System.out.println(s);}Value3 v = new Value3(10);static Value3 v1, v2;static {//此即为static块prt("v1.c=" + v1.c + " v2.c=" + v2.c);v1 = new Value3(27);prt("v1.c=" + v1.c + " v2.c=" + v2.c);v2 = new Value3(15);prt("v1.c=" + v1.c + " v2.c=" + v2.c);}publicstaticvoid main(String[] args) {Count ct = new Count();prt("ct.c=" + ct.v.c);prt("v1.c=" + v1.c + " v2.c=" + v2.c);v1.inc();prt("v1.c=" + v1.c + " v2.c=" + v2.c);prt("ct.c=" + ct.v.c);}}

结果为:
v1.c=0 v2.c=0
v1.c=27 v2.c=27
v1.c=15 v2.c=15
ct.c=10
v1.c=10 v2.c=10
v1.c=11 v2.c=11
ct.c=11

这个程序展示了静态初始化的各种特性。如果你初次接触Java,结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是,static定义的变量会优先于任何其它非static变量,不论其出现的顺序如何。正如在程序中所表现的,虽然v出现在v1和v2的前面,但是结果却是v1和v2的初始化在v的前面。在static{后面跟着一段代码,这是用来进行显式的静态变量初始化,这段代码只会初始化一次,且在类被第一次装载时。如果你能读懂并理解这段代码,会帮助你对static关键字的认识。在涉及到继承的时候,会先初始化父类的static变量,然后是子类的,依次类推。


静态类
通常一个普通类不允许声明为静态的,只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用,而不需实例一个外部类。

publicclass StaticCls {publicstaticvoid main(String[] args) {OuterCls.InnerCls oi = newOuterCls.InnerCls();}}classOuterCls {publicstaticclass InnerCls {InnerCls() {System.out.println("InnerCls");}}} 

结果为:InnerCls



final特点:
1,这个关键字是一个修饰符,可以修饰类,方法,变量。
2,被final修饰的类是一个最终类,不可以被继承。
3,被final修饰的方法是一个最终方法,不可以被覆盖。
4,被final修饰的变量是一个常量,只能赋值一次。

final成员  当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。其初始化可以在两个地方,一是其定义处,也就是说在final变量定义时直接给其赋值,二是在构造函数中。这两个地方只能选其一,要么在定义时给值,要么在构造函数中给值,不能同时既在定义时给了值,又在构造函数中给另外的值。下面这段代码演示了这一点:
import java.util.List;import java.util.ArrayList;import java.util.LinkedList;public class Bat{    final PI=3.14;          //在定义时便给址值    final int i;            //因为要在构造函数中进行初始化,所以此处便不可再给值    final List list;        //此变量也与上面的一样    Bat(){        i=100;        list=new LinkedList();    }    Bat(int ii,List l){        i=ii;        list=l;    }    public static void main(String[] args){        Bat b=new Bat();        b.list.add(new Bat());        //b.i=25;        //b.list=new ArrayList();        System.out.println("I="+b.i+" List Type:"+b.list.getClass());        b=new Bat(23,new ArrayList());        b.list.add(new Bat());        System.out.println("I="+b.i+" List Type:"+b.list.getClass());    }}

 此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法,这使你有了一点灵活性。如Bat的两个重载构造函数所示,第一个缺省构造函数会为你提供默认的值,重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性,你只需要在定义时便给定其值并永不变化,这时就不要再用这种方法。在main方法中有两行语句注释掉了,如果你去掉注释,程序便无法通过编译,这便是说,不论是i的值或是list的类型,一旦初始化,确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型,输出结果中显示了这一点:
I=100 List Type:class java.util.LinkedListI=23 List Type:class java.util.ArrayList

final定义的参数

对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法。另外方法中的内部类在用到方法中的参变量时,此参变也必须声明为final才可使用,如下代码所示:
public class INClass{   void innerClass(final String str){        class IClass{            IClass(){                System.out.println(str);            }        }        IClass ic=new IClass();    }  public static void main(String[] args){      INClass inc=new INClass();      inc.innerClass("Hello");  }}

final方法与final类
final方法  将方法声明为final,那就说明你已经知道这个方法提供的功能已经满足你要求,不需要进行扩展,并且也不允许任何从此类继承的类来覆写这个方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。另外有一种被称为inline的机制,它会使你在调用final方法时,直接将方法主体插入到调用处,而不是进行例行的方法调用,例如保存断点,压栈等,这样可能会使你的程序效率有所提高,然而当你的方法主体非常庞大时,或你在多处调用此方法,那么你的调用主体代码便会迅速膨胀,可能反而会影响效率,所以你要慎用final进行方法定义。final类  当你将final用于类身上时,你就需要仔细考虑,因为一个final类是无法被任何人继承的,那也就意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员,你可以定义其为final,也可以不是final。而对于方法,由于所属类为final的关系,自然也就成了final型的。你也可以明确的给final类中的方法加上一个final,但这显然没有意义。  下面的程序演示了final方法和final类的用法:
final class final{    final String str="final Data";    public String str1="non final data";    final public void print(){        System.out.println("final method.");    }    public void what(){        System.out.println(str+"\n"+str1);    }}public class FinalDemo {   //extends final 无法继承     public static void main(String[] args){        final f=new final();        f.what();        f.print();    }}

从程序中可以看出,final类与普通类的使用几乎没有差别,只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出,只是记住慎用。



抽象类的特点:
1,抽象方法只能定义在抽象类中,抽象类和抽象方法必须由abstract关键字修饰(可以描述类和方法,不可以描述变量)。
2,抽象方法只定义方法声明,并不定义方法实现。
3,抽象类不可以被创建对象(实例化)。
4,只有通过子类继承抽象类并覆盖了抽象类中的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。

例:

抽象类:

abstract class A {  public String getName();  public void call() {    getName();  }}public class B extend A{ public String getName() {  return "B";  }}

调用类:

public class C {  public static void main(String[] args) {    A a = new B();    a.call();  }}


方法重载:同一类中的多个方法,类名相同,但是他们的参数列表不同。

重载的定义是:在一个类中,如果出现了两个或者两个以上的同名函数,只要它们的参数的个数,或者参数的类型不同,即可称之为该函数重载了。
如何区分重载:当函数同名时,只看参数列表。和返回值类型没关系。

例:

class A{public void display(int a){System.out.println(“数字是”+a);}publlic void display(char a){System.out.println(“字符是”+a);}public void display(String s){System.out.println("字符串是"+s);}}
这样一来,通过对不同类型的参数对比,java就能自动选用合适的方法,而不用分别声明。


封装:将类的某些信息隐藏在类的内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。

封装的好处1.方便加入控制语句;2.方便修改实现;3.隐藏类的实现细节;4.只能通过规定方法访问数据。

例:

public class Man{//对属性的封装,一个人的姓名,年龄,妻子都是这个对象(人)的私有属性private String name;private int age;private Woman wife;//对该人对外界提供方法的封装,可以设定妻子,姓名,年龄也可以获得男人的姓名和年龄  // 方法封装  public void setWife(Woman wife) {  this.wife = wife;  }  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  }  public class Woman {  // 属性封装  private String name;  private int age;  private Man husband;  // 方法封装  public String getName() {  return name;  }  public void setName(String name) {  this.name = name;  }  public int getAge() {  return age;  }  public void setAge(int age) {  this.age = age;  }  public Man getHusband() {  return husband;  }  public void setHusband(Man husband) {  this.husband = husband;  }  }/*** 仔细看就会发现,Man类没有提供getWife的方法,这是因为男人不想让自己的妻子被外界访问,** 接下来呢,就是封装可以把一个对象的属性私有,而提供一些可以被外界访问的属性的方法,** 比如说,name属性,Man和Woman类都有相应的get和set方法,外界都可以通过这些方法访问和修改** 同时对一些对象不想让外界访问的属性,就不提供其方法,比如说Man的wife属性,就没有get方法** 外界是不能得到Man类的wife属性的**/

封装的作用

1、对象的数据封装特性彻底消除了传统结构方法中数据与操作分离所带来的种种问题,提高了程序的可复用性和可维护性,降低了程序员保持数据与操作内容的负担。

2、对象的数据封装特性还可以把对象的私有数据和公共数据分离开,保护了私有数据,减少了可能的模块间干扰,达到降低程序复杂性、提高可控性的目的。


总结:以上是我对Java关键字、抽象类、方法重载、封装的一些笔记,通过例子与理论结合,我们能够很深入去理解Java的这部分内容。


0 0
原创粉丝点击