您的位置:首页 > 编程语言 > Java开发

尚硅谷java学习笔记——5.高级类特性2

2016-10-11 16:44 579 查看
5.1关键字static

 static ,静态的,可以用来修饰  属性、方法、代码块(或初始化块)、内部类

static修饰属性(类变量):

1、由类创建的所有的对象,都共用这一个属性

2、当其中一个对象对此属性进行修改,会导致其他对象对此属性的一个调用。vs实例变量(非static修饰的属性,各自拥有一套副本)

3、类变量随着类的加载而加载的,而且独一份

4、静态的变量可以直接通过“类.类变量”的形式来调用

5、类变量的加载时要早于对象。当有对象后,可以“对象.类变量”,使用。但是“类.实体变量”不行

6、类变量存在于静态域中



static修饰方法(类方法)

1、随着类的加载而加载,在内存中也是独一份

2、可以直接通过“类.类方法”的方式调用

3、在静态方法内部可以调用静态的属性和方法,而不能调用非静态的属性和方法,反之非静态方法的可以调用静态的属性和方法

>静态的方法内是不可以有this或super关键字的!

注:静态的结构(static的属性、方法、代码块、内部类)的生命周期要早于非静态的生命周期,被回收也要晚于非静态

5.2单(Singleton)设计模式

设计模式:设计模式是在大量的实践中总结和理论化之后优选的代码结构、编程风格、以及解决问题的思考方式

单例设计模式:

1、解决的问题:使得一个类只能够创建一个对象。

2、如何实现?

//饿汉式

      1、私有化构造器,使得在类的外部不能够调用此构造器

      2、在类的内部创建一个类的实例

      3、私有化此对象,通过公共的方法来调用

      4、此公共的方法,只能通过类来调用,因为设置为static的,同时类的实例也必须是static声明的

//懒汉式:可能存在线程安全问题

     1、方法外面只声明静态变量,不实例化

     2、在方法里判断变量是否为空,如果为空再实例化

5.3 代码块

关于赋值的操作:1、默认的初始化  2、显式的初始化 或代码块初始化(按照代码的顺序执行) 3、构造器中   4、通过方法对对象的相应属性进行修改        (初始化就是赋值)

 类的第四个成员:初始化块(或代码块)

1、代码块如果修饰的话,那么只能使用static

2、分类:

    静态代码块:1、里面可以有输出语句

                            2、随着类的加载而加载,而且只被加载一次

                            3、对个静态代码块之间按照顺序结构执行

                            4、静态代码块的执行要早于非静态代码块的执行

                            5、静态的代码块中只能执行静态的结构(类属性、类方法)

    非静态代码块:1、可以对类的属性进行初始化操作,同时也可以调用本类声明的方法(静态或非静态)

                                2、里面可以有输出语句

                                3、一个类中可以有多个非静态代码块,那么顺序执行

                                4、每创建一个类的对象非静态代码块就执行一次

                                5、非静态代码块的执行要早于构造器

5.4关键字 final

可以用来修饰类、属性、方法

1、final修饰类:这个类就不能被继承。如:String类、StringBuffer类、System类

2、final修饰方法:不能被重写。 如:Object类的getClass()

3、final修饰属性,此属性就是一个常量。一旦初始化后,不能再被赋值。习惯上,常量用大写字符表示,此常量必须显示的赋值(或通过代码块、构造器),不能使用默认初试化

常量用static final修饰:全局变量

5.5抽象类(abstract class)

abstract:抽象的,可以用来修饰类、方法

1、abstract修饰类:抽象类

      1、抽象类不可以被实例化

      2、抽象类有构造器(凡是类都有构造器)

      3、抽象方法所在的类,一定是抽象类

      4、抽象类中可以没有抽象方法

2、abstract修饰方法:抽象方法

      1、格式:没有方法体,包括{},如:public abstract void eat( );

      2、抽象方法只保留方法的功能,而具体的执行,交给子类

      3、若子类继承抽象类,并重写了所有抽象方法,则此类是一个“实体类”,即可以实例化

      4、若子类继承抽象类,没有重写所有的抽象方法,意味着此类中仍有抽象方法,则此类必须声明为抽象类

abstract不能用来修饰属性、构造器、private、final、static

 

模板方法设计模式(TempateMethod)

抽象类体现的就是一种模板的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会保留抽象类的行为方式

解决的问题:

      当功能额内部一部分实现是确定,一部分实现不确定的,这时可以把不确定的部分暴露出去,让子类去实现

      编写一个抽象父类,父类提供了多个子类的抽象方法,并把一个或多个方法留给其子类去实现,就是一种模板模式

abstract class Template{
public final void getTime(){
long start = System.currentTimeMillis();
code();
long end = System.currentTimeMillis();
System.out.println("执行时间是:"+(end - start));
}
public abstract void code();
}
class SubTemplate extends Template{
public void code(){
for(int i = 0;i<10000;i++){
System.out.println(i);
}
}
}


5.6接口(1)

与类是并列的关系

有了接口就可以得到多重继承的效果

接口是抽象方法和常量值的定义的集合,为了表明某种功能

本质上讲,接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义,而没有变量和方法的实现,不能包含一般方法

接口是没有构造器的。

实现接口的类,必须重写其中所有的抽象方法,方可实例化。若没有重写所有的抽象方法,则此类认为一个抽象类

类可以实现多个接口。java中的继承是单继承的。

接口之间可以继承而且可以多继承



接口中      所有的常量都用public static final修饰(虽然写的是int I=12,但系统自动会认为是public static final int I=12)

                  抽象方法:所有的都用public abstract修饰

接口用法总结:

1、通过接口可以实现不相关类的相同行为,而不需要考虑这些类的层次关系

2、通过接口可以指明多个类需要实现的方法,一般用于定义对象的扩张功能

3、接口主要用来定义规范。解除耦合关系

工厂模式(FactoryMethod)

概述:定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使一个类的实例化延迟到其子类。

适用性:

             1、当一个类不知道它所必须创建的对象的类的时候。

             2、当一个类希望由它的子类来指定它所创建的对象的时候

             3、当类将创建对象的职务委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候



package day11;

public class TestFactorMethod {
public static void main(String[] args) {
IWorkFactory i=new StudentWorkFacory();
i.getWork().doWork();

IWorkFactory j=new TeacherWorkFactory();
j.getWork().doWork();
}
}

interface IWorkFactory{
Work getWork();
}

class StudentWorkFacory implements IWorkFactory{
@Override
public Work getWork() {
return new StudentWork();
}
}

class TeacherWorkFactory implements IWorkFactory{
@Override
public Work getWork() {
return new TeacherWork();
}
}

interface Work{
void doWork();
}

class TeacherWork implements Work{
@Override
public void doWork() {
System.out.println("老师批改作业");
}
}

class StudentWork implements Work{
@Override
public void doWork() {
System.out.println("学生写作业");
}
}


总结:

         FactoryMethod模式是设计模式中应用最为广泛的模式,在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要。FactoryMethod解决的就是这个问题,它通过面向对象的手法,将所要创建的具体对象的创建工作延迟到了子类,从而提供了一种扩展的策略,较好的解决了这种紧耦合的关系。

代理模式(Proxy)

概述:为其他对象提供一种代理以控制对这个对象的访问



package day11;

public class TestProxy {
public static void main(String[] args) {
Object o=new ProxyObject();
o.action();
}
}

interface Object{
void action();
}

//代理类
class ProxyObject implements Object{
Object obj;

public ProxyObject(){
System.out.println("代理类创建成功");
obj=new ObjectImpl();
}

@Override
public void action() {
obj.action();
}
}

//被代理类
class ObjectImpl implements Object{
@Override
public void action() {
System.out.println("======被代理类开始执行==========");
System.out.println("======我是代理类==========");
System.out.println("======被代理类执行结束==========");
}
}


5.7内部类

类的第5个成员:内部类

类的内部再定义类

内部类的分类:1、成员内部类:声明在类内部且方法外的

                                              是外部类的一个成员:可以有修饰符(4个);可以用static修饰;可以用final修饰;可以用abstract修饰;可以调用外部类的成员、方法

                 具有类的特点:abstract  ;可以在其内部定义方法、属性、构造器

                            2、局部内部类:声明在类的方法里

关于内部类,掌握三点:1、如何创建成员内部类的对象:创建非静态内部类的对象,必须先创建外部类的对象,通过对象来调用内部类的构造器//Person.Bird b=p.new Bird();

                                            2、如何区分调用外部类、内部类的变量(尤其是重名时)

    3、局部内部类的使用 

class OuterClass{
//局部内部类
//如下的使用方式较少
public void method1(){
class InnnerClass{
}
}
//常常使用一个方法,使其返回值为某个类或接口的对象。而这个类或接口在方法内部创建
//使用方式一
public Comparable getComparable(){
//1.创建一个实现Comparable接口的类:局部内部类
class MyComparable implements Comparable{
@Override
public int compareTo(java.lang.Object o) {
return 0;
}
}
//2.返回一个实现类的对象
return new MyComparable();
}
//使用方式二
public Comparable getComparable1(){
//返回一个实现Comparable接口的匿名内部类的对象
return new Comparable(){
@Override
public int compareTo(java.lang.Object o) {
// TODO Auto-generated method stub
return 0;
}
};
}
}


java中方法的传递机制:只要值传递,基本数据类型传递的是基本数据类型的值,引用数据类型传递的是引用数据类型的地址值



abstract class 和interface 有什么区别? 【基础】

答:声明方法的存在而不去实现它的类被叫做抽象类(abstract class),它用于要创建一个体现某些基本行为的类,

并为该类声明方法,但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量,其类型

是一个抽象类,并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们

父类中的所有抽象方法提供实现,否则它们也是抽象类。取而代之,在子类中实现该方法。知道其行为的其它类

可以在类中实现这些方法

接口(interface)是抽象类的变体。在接口中,所有方法都是抽象的。多继承性可通过实现这样的接口而获得。

接口中的所有方法都是抽象的,没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似,

除了该实现类不能从接口定义中继承行为。当类实现特殊接口时,它定义(即将程序体给予)所有这种接口的方法。

然后,它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类,它允许使用接口名作为引用变量的

类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换,instanceof 运算符可以用来决定某对象

的类是否实现了接口

--------------------------------------------------------------------------------------------------------------------------------------------------------------

abstract 的method 是否可同时是static,是否可同时是native,

是否可同时是synchronized?

答:都不能

--------------------------------------------------------------------------------------------------------------------------------------------------------------

是否可以从一个static方法内部发出对非static方法的调用?

答:不可以,如果其中包含对象的method();不能保证对象初始化.

--------------------------------------------------------------------------------------------------------------------------------------------------------------

写一个Singleton出来

Singleton模式主要作用是保证在Java应用程序中,一个类Class只有一个实例存在。

一般Singleton模式通常有几种种形式:

第一种形式: 定义一个类,它的构造函数为private的,它有一个static的private的该类变量,在类初始化时实例话,通过一个public的getInstance方法获取对它的引用,继而调用其中的方法。

public class Singleton {

private Singleton(){}

      //在自己内部定义自己一个实例,是不是很奇怪?

      //注意这是private 只供内部调用

      private static Singleton instance = new Singleton();

      //这里提供了一个供外部访问本class的静态方法,可以直接访问  

      public static Singleton getInstance() {

        return instance;   

      } 

    } 

    第二种形式: 

public class Singleton { 

  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  //这个方法比上面有所改进,不用每次都进行生成对象,只是第一次     

  //使用时生成实例,提高了效率!

  if (instance==null)

    instance=new Singleton();

return instance;   } 



其他形式:

定义一个类,它的构造函数为private的,所有方法为static的。

一般认为第一种形式要更加安全些 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?

答案是:   接口可以继承接口。抽象类可以实现(implements)接口,

抽象类可继承实体类,但实体类必须不能是如下两种情况之一:   

1,final修饰符修饰的类是不能的

2,如果此实体类有且仅有私有的构造函数也是不能的。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口)

答:匿名的内部类是没有名字的内部类。不能extends(继承) 其它类,但一个内部类可以作为一个接口,由另一个内部类实现

--------------------------------------------------------------------------------------------------------------------------------------------------------------

Static Nested Class 和 Inner Class的不同

答:Nested Class (一般是C++的说法),Inner Class (一般是JAVA的说法)。

Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。

注: 静态内部类(Inner Class)意味着

1创建一个static内部类的对象,不需要一个外部类对象,2不能从一个static内部类的一个对象访问一个外部类对象

--------------------------------------------------------------------------------------------------------------------------------------------------------------

谈谈final, finally, finalize的区别

答:final—修饰符(关键字)如果一个类被声明为final,意味着它不能再派生出新的子类,不能作为父类被继承。

因此一个类不能既被声明为 abstract的,又被声明为final的。将变量或方法声明为final,可以保证它们在使用中不被改变。

被声明为final的变量必须在声明时给定初值,而在以后的引用中只能读取,不可修改。被声明为final的方法也同样只能使用,

不能重载

finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常,那么相匹配的 catch 子句就会执行,

然后控制就会进入 finally 块(如果有的话)

finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。

这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类

都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除

对象之前对这个对象调用的

--------------------------------------------------------------------------------------------------------------------------------------------------------------

如下程序是否可通过编译?

public class Something {

   public int addOne(final int x) {

       return ++x;

   }

}

这个比较明显。

答案: 错。int x被修饰成final,意味着x不能在addOne method中被修改。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

abstract class Name {

   private String name;

   public abstract boolean isStupidName(String name) {}

}

这有何错误?

答案: 错。abstract method必须以分号结尾,且不带花括号。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

如下程序是否可通过编译?

public class Something {

   public static void main(String[] args) {

       Other o = new Other();

       new Something().addOne(o);

   }

   public void addOne(final Other o) {

       o.i++;

   }

}

class Other {

   public int i;

}

和上面的很相似,都是关于final的问题,这有错吗?

答案: 正确。在addOne method中,参数o被修饰成final。如果在addOne method里我们修改了o的reference

(比如: o = new Other();),那么如同上例这题也是错的。但这里修改的是o的member vairable

(成员变量),而o的reference并没有改变。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

public class Something {

     public static void main(String[] args) {

        Something s = new Something();

        System.out.println("s.doSomething() returns " + doSomething());

    }

    public String doSomething() {

        return "Do something ...";

    }

}

 看上去很完美。

答案: 错。看上去在main里call doSomething没有什么问题,毕竟两个methods都在同一个class里。

但仔细看,main是static的。static method不能直接call non-static methods。

可改成"System.out.println("s.doSomething() returns " + s.doSomething());"。

同理,static method不能访问non-static instant variable。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

是否可以通过编译?

abstract class Something {

   private abstract String doSomething ();

}

答案: 错。abstract的methods不能以private修饰。abstract的methods就是让子类implement(实现)具体细节的,怎么可以用private把abstract

method封锁起来呢? (同理,abstract method前不能加final)。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

是否可以通过编译?

class Something {

    int i;

    public void doSomething() {

        System.out.println("i = " + i);

    }



答案: 正确。输出的是"i = 0"。int i属於instant variable (实例变量,或叫成员变量)。instant variable有default value。

int的default value是0。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

接上题

class Something {

    final int i;

    public void doSomething() {

        System.out.println("i = " + i);

    }

}

和上面一题只有一个地方不同,就是多了一个final。这难道就错了吗?

答案: 错。final int i是个final的instant variable (实例变量,或叫成员变量)。final的instant variable没有default value,

必须在constructor (构造器)结束之前被赋予一个明确的值。可以修改为"final int i = 0;"。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

interface  A{

   int x = 0;

}

class B{

   int x =1;

}

class C extends B implements A {

   public void pX(){

      System.out.println(x);  //super.x   A.x

   }

   public static void main(String[] args) {

      new C().pX();

   }

}

答案:错误。在编译时会发生错误(错误描述不同的JVM有不同的信息,意思就是未明确的x调用,

两个x都匹配(就象在同时import java.util和java.sql两个包时直接声明Date一样)。对于父类的变量,可以用super.x来明确,

而接口的属性默认隐含为 public static final.所以可以通过A.x来明确。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

写出程序结果

interface A{}  

class B implements A

{
public String func()
{
return "func";
}

}

class Demo

{
public static void main(String[] args)
{
A a=new B();
System.out.println(a.func());
}

}

编译失败:因为A接口中并未定义func方法。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

写出程序结果

class TD

{
int y=6;
class Inner
{
static int y=3;  
void show()
{
System.out.println(y);
}
}

}

class TC

{
public static void main(String[] args)
{
TD.Inner ti=new TD().new Inner();
ti.show();
}

}

编译失败,非静态内部类中不可以定义静态成员。

内部类中如果定义了静态成员,该内部类必须被静态修饰。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

interface Test{
void func();

}

class Demo{
public static void main(String[] args){
//补足代码;(匿名内部类)

//new Demo().show(new Test(){
public void func(){

}
});

}
void show(Test t){
t.func();
}

}

--------------------------------------------------------------------------------------------------------------------------------------------------------------

写出程序结果

public class Demo

{     
private static int j = 0; 
private static boolean methodB(int k)
{
j += k; 
return true; 
}
public static void methodA(int  i)


        boolean b;   
b = i < 10 | methodB (4); 
b = i < 10 || methodB (8); 
}
public static void main (String args[] )
{
methodA (0); 
System.out.println(j); 


}

//4

--------------------------------------------------------------------------------------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: