抽象类不能实例化对象

Posted THISISPAN

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了抽象类不能实例化对象相关的知识,希望对你有一定的参考价值。

抽象类无法实例化,无法创建对象。现实生活中也有抽象类的类子,比如说人类是一个抽象类,无法创建一个叫人类的对象,人继承人类来创建对象。况且抽象类中的抽象方法只有声明,没有主体,如果实例化了,又如何去实现调用呢?

 

sleep和wait的区别有:
  1,这两个方法来自不同的类分别是Thread和Object
  2,最主要是sleep方法没有释放锁,而wait方法释放了锁,使得敏感词线程可以使用同步控制块或者方法。
  3,wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在
    任何地方使用
   synchronized(x){
      x.notify()
     //或者wait()
   }
   4,sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常


Java中的多线程是一种抢占式的机制,而不是分时机制。抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行。 
共同点 : 
1. 他们都是在多线程的环境下,都可以在程序的调用处阻塞指定的毫秒数,并返回。 
2. wait()和sleep()都可以通过interrupt()方法 打断线程的暂停状态 ,从而使线程立刻抛出InterruptedException。 
如果线程A希望立即结束线程B,则可以对线程B对应的Thread实例调用interrupt方法。如果此刻线程B正在wait/sleep/join,则线程B会立刻抛出InterruptedException,在catch() {} 中直接return即可安全地结束线程。 
需要注意的是,InterruptedException是线程自己从内部抛出的,并不是interrupt()方法抛出的。对某一线程调用 interrupt()时,如果该线程正在执行普通的代码,那么该线程根本就不会抛出InterruptedException。但是,一旦该线程进入到 wait()/sleep()/join()后,就会立刻抛出InterruptedException 。 
不同点 :  
1.每个对象都有一个锁来控制同步访问。Synchronized关键字可以和对象的锁交互,来实现线程的同步。 
sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。 
2.wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用 
3.sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常 
4.sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。
5.wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。
 
3.a++可以理解为当访问a之后再对a进行加一操作
以下程序的运行结果是()
1
2
3
4
5
6
7
8
9
10
11
public class Increment
{
    public static void main(String args[])
    {
        int a;
        a = 6;
        System.out.print(a);
        System.out.print(a++);
        System.out.print(a);
    }
}

正确答案: B   你的答案: B (正确)

666
667
677
676

4.下面程序的运行结果是
String str1 = "hello";
String str2 = "he" + new String("llo");
System.err.println(str1 == str2);

正确答案: B   你的答案: 空 (错误)

true
false
exception
无输出
String str1 = "hello";这里的str1指的是方法区的字符串常量池中的“hello”,编译时期就知道的; String str2 = "he" + new String("llo");这里的str2必须在运行时才知道str2是什么,所以它是指向的是堆里定义的字符串“hello”,所以这两个引用是不一样的。

如果用str1.equal(str2),那么返回的是True;因为两个字符串的内容一样。

5.
有以下类定义:
1
2
3
4
5
6
7
8
9
10
11
abstract class Animal{
    abstract void say();
}
public class Cat extends Animal{
    public Cat(){
        System.out.printf("I am a cat");
    }
    public static void main(String[] args) {
        Cat cat=new Cat();
    }
}
运行后:

正确答案: B   你的答案: B (正确)

I am a cat
Animal能编译,Cat不能编译
Animal不能编译,Cat能编译
编译能通过,但是没有输出结果

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点区别:

1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。

2)抽象类不能用来创建对象;

3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

在其他方面,抽象类和普通的类并没有区别。

 

5.

假设如下代码中,若t1线程在t2线程启动之前已经完成启动。代码的输出是()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void main(String[]args)throws Exception {
    final Object obj = new Object();
    Thread t1 = new Thread() {
        public void run() {
            synchronized (obj) {
                try {
                    obj.wait();
                    System.out.println("Thread 1 wake up.");
                catch (InterruptedException e) {
                }
            }
        }
    };
    t1.start();
    Thread.sleep(1000);//We assume thread 1 must start up within 1 sec.
    Thread t2 = new Thread() {
        public void run() {
            synchronized (obj) {
                obj.notifyAll();
                System.out.println("Thread 2 sent notify.");
            }
        }
    };
    t2.start();
}

正确答案: B   你的答案: C (错误)

Thread 1 wake up
Thread 2 sent notify.
Thread 2 sent notify.
Thread 1 wake up
A、B皆有可能
程序无输出卡死

选择B
执行obj.wait();时已释放了锁,所以t2可以再次获得锁,然后发消息通知t1执行,但这时t2还没有释放锁,所以肯定是执行t2,然后释放锁,之后t1才有机会执行。
notify()就是对对象锁的唤醒操作。但有一点需要注意的是notify()调用后,并不是马上就释放对象锁的,而是在相应的synchronized(){}语句块执行结束,自动释放锁后,JVM会在wait()对象锁的线程中随机选取一线程,赋予其对象锁,唤醒线程,继续执行。这样就提供了在线程间同步、唤醒的操作。
 
下列选项中是正确的方法声明的是?()

正确答案: A B C D   你的答案: A B C D (正确)

protected abstract void f1();
public final void f1() {}
static final void fq(){}
private void f1() {}

1.接口和抽象类都可以作为声明使用,但不能实例化。只能用来声明。


在jdk1.5的环境下,有如下4条语句:
1
2
3
4
Integer i01 = 59;
int i02 = 59;
Integer i03 =Integer.valueOf(59);
Integer i04 = new Integer(59)。
以下输出结果为false的是:

正确答案: C   你的答案: A (错误)

System.out.println(i01== i02);
System.out.println(i01== i03);
System.out.println(i03== i04);
System.out.println(i02== i04);
JVM中一个字节以下的整型数据会在JVM启动的时候加载进内存,除非用new Integer()显式的创建对象,否则都是同一个对象
所有只有i04是一个新对象,其他都是同一个对象。所有A,B选项为true
C选项i03和i04是两个不同的对象,返回false
D选项i02是基本数据类型,比较的时候比较的是数值,返回true
 
 
10.javax是Sun公司提供的一个扩展包,算是对原 JAVA 包的一些优化处理,现在已经有很多都是基于JAVAX的程序开发而不是java包。
11.

使用 Java 技术开发 WEB 应用程序 , 深入了解 Servlet 的机制对应用的开发将有重要的推动作用 . 而想深入了解 Servlet 的机制就不得不了解 javax.servlet 包 .

 

javax.servlet 包中包含了 7 个接口 ,3 个类和 2 个异常类 , 它们分别是 :

 

接口 :RequestDispatcher,Servlet,ServletConfig,ServletContext,ServletRequest,ServletResponse 和 SingleThreadModel

 

类 :GenericServlet,ServletInputStream 和 ServletOutputStream

 

异常类 :ServletException 和 UnavailableException

 

Servlet 的生命周期

 

在 Servlet 的接口中定义了一个 Servlet 的生命周期方法 , 分别是 Init,Service 和 Destroy

 

演示了 Servlet 生命周期方法的简单 Servlet:

 

import javax.servlet.*;

import java.io.IOException;

 

public class PrimitiveServlet implements Servlet {

 

  public void init(ServletConfig config) throws ServletException {

    System.out.println("init");

  }

 

  public void service(ServletRequest request, ServletResponse response)

    throws ServletException, IOException {

    System.out.println("service");

  }  

  public void destroy() {

    System.out.println("destroy");

  }

 

  public String getServletInfo() {

    return null;

  }

  public ServletConfig getServletConfig() {

    return null;

  }

 

}

 

在 Servlet 中如何获取 ServletConfig 对象 ?

 

在 Servlet 的 Init 方法中 ,Servlet Container 将会传入一个 ServletConfig 对象 , 开发人员可以通过这个对象获取在 web.xml 文件中定义的Servlet 初始化参数 .

 

下面是一个获取 Servlet 初始参数的示例 :

 

import javax.servlet.*;

import java.util.Enumeration;

import java.io.IOException;

 

public class ConfigDemoServlet implements Servlet {

 

  public void init(ServletConfig config) throws ServletException {

    Enumeration parameters = config.getInitParameterNames();

    while (parameters.hasMoreElements()) {

      String parameter = (String) parameters.nextElement();

      System.out.println("Parameter name : " + parameter);

      System.out.println("Parameter value : " +

        config.getInitParameter(parameter));

    }

  }

 

  public void destroy() {

  }

 

  public void service(ServletRequest request, ServletResponse response)

    throws ServletException, IOException {

  }

 

  public String getServletInfo() {

    return null;

  }

 

  public ServletConfig getServletConfig() {

    return null;

  }

}

如何获取 ServletContext 对象 ?

可以通过 ServletConfig 对象的 getServletContext 方法获取 ServletContext 对象

import javax.servlet.*;

import java.util.Enumeration;

import java.io.IOException;

 

public class ContextDemoServlet implements Servlet {

  ServletConfig servletConfig;

 

  public void init(ServletConfig config) throws ServletException {

    servletConfig = config;

  }

 

  public void destroy() {

  }

 

  public void service(ServletRequest request, ServletResponse response)

    throws ServletException, IOException { 

    ServletContext servletContext = servletConfig.getServletContext();

    Enumeration attributes = servletContext.getAttributeNames();

    while (attributes.hasMoreElements()) {

      String attribute = (String) attributes.nextElement();

      System.out.println("Attribute name : " + attribute);

      System.out.println("Attribute value : " +

        servletContext.getAttribute(attribute));

    }

 

    System.out.println("Major version : " +

servletContext.getMajorVersion());

    System.out.println("Minor version : " +

servletContext.getMinorVersion());

    System.out.println("Server info : " + servletContext.getServerInfo());

  }

 

  public String getServletInfo() {

    return null;

  }

  public ServletConfig getServletConfig() {

    return null;

  }

 

}

如何在 Servlet 之间共享信息 ?

我们可以通过 ServletContext 来维护在不同 Servlet 之间共享的信息 .

如何解决 Servlet 的多 Thread 问题 ?

如果 Servlet 需要读写外部资源 , 我们需要考虑 Thread 的问题 , 我们可以使用声明性接口 SingleThreadModel 来避免多 Thread 之间的资源冲突问题 . 但是需要注意的是 , 如果 Servlet 仅仅只是读外部资源的话 , 我们通常不应该实现这个接口 . 如果实现这个接口 ,Servlet 在同一时刻只能服务一个用户请求 , 后至的用户请求必须在队列中等待

 

10.

Which statement declares a variable a which is suitable for referring to an array of 50 string objects?

正确答案: B C F   你的答案: E (错误)

char a[][];
String a[];
String[] a;
Object a[50];
String a[50];
Object a[];
在java 中,声明一个数组时,不能直接限定数组长度,只有在创建实例化对象时,才能对给定数组长度.。
如下,1,2,3可以通过编译,4,5不行。而String是Object的子类,所以上述BCF均可定义一个存放50个String类型对象的数组。
1. String a[]=new String[50];
2. String b[];
3. char c[];
4. String d[50];
5. char e[50];

 

    • Java语言中,中文字符所占的字节数取决于字符的编码方式,一般情况下,采用ISO8859-1编码方式时,一个中文字符与一个英文字符一样只占1个字节;采用GB2312或GBK编码方式时,一个中文字符占2个字节;而采用UTF-8编码方式时,一个中文字符会占3个字节。

      在C++中

      在C++中,char是基础数据类型,8位,1个字节。byte不是基础数据类型,一般是typedef unsigned char byte;这样子的,也就是说,byte其实是unsigned char类型,那么也是8位,1个字节。不同的是,char可以表示的范围是-128-127,而byte可以表示的范围是0-255。

      在Java中

      在java中,char和byte都是基础数据类型,其中的byte和C++中的char类型是一样的,8位,1个字节,-128-127。但是,char类型,是16位,2个字节, ‘\u0000‘-‘\uFFFF‘。

      为什么java里的char是2个字节?

      因为java内部都是用unicode的,所以java其实是支持中文变量名的,比如string 世界 = "我的世界";这样的语句是可以通过的。

      综上,java中采用GB2312或GBK编码方式时,一个中文字符占2个字节,而char是2个字节,所以是对的
      发表于 2015-10-07 14:54:11回复(0)
    • A.在Java中,char类型占两个字节,一个汉字也占两个字节,所以是正确的。

以上是关于抽象类不能实例化对象的主要内容,如果未能解决你的问题,请参考以下文章

继承一个抽象类,并实例化抽象类中定义的方法,这个方法返回spring注入的一个对象,值一直为空?

java抽象类及接口

PHP能在类中实例化一个类吗

17_JavaSE_抽象类和封装

面向对象---多态-抽象

元类,归一化设计,抽象类