谁会这几个java判断题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了谁会这几个java判断题?相关的知识,希望对你有一定的参考价值。

小女初学java,请不要笑话噢!^-^(请仔细考虑回答!!!)

1.一个abstract类可以被声明为final类( )
为什么啊?什么abstract类啊?能否举例说一下啊?谢了!
2.一个abstract类不能被实例化( )
实例化是什么意思啊?
3.一个static变量表明该变量只有一个副本( )
static变量,副本又是什么呢?
4.一个final方法使用非JAVA的其它语言实现,代码位于本地机上( )
什么是final 方法呢?

各位感觉自己的JAVA学得怎么样啊,说说这几道题吧!谢谢了!

1.错
abstract就是抽象类,

一个类不能既被声明为 abstract的,又被声明为final的
因为抽象类用于被继承,而声明为final的类不能被继承,矛盾了

Java语言中,用abstract 关键字来修饰一个类时,这个类叫做抽象类,用abstract 关键字来修饰一个方法时,这个方法叫做抽象方法。格式如下:
abstract class abstractClass … //抽象类
abstract returnType abstractMethod([paramlist]) //抽象方法

抽象类必须被继承,抽象方法必须被重写。抽象方法只需声明,无需实现;抽象类不能被实例化,抽象类不一定要包含抽象方法。若类中包含了抽象方法,则该类必须被定义为抽象类。

2.对,实例化如下:
class A
int a;
A()
a = 0



public B
public static void main(String[] args)
A a;//这是声明
a = new A();//这是实例化
System.out.println(a.a);
//输出等于零。



3.副本即一个实例。static表示静态的。
用static 关键字可以声明类变量和类方法,其格式如下:
static type classVar;
static returnType classMethod(paramlist)



如果在声明时不用static 关键字修饰,则声明为实例变量和实例方法。
1) 实例变量和类变量
每个对象的实例变量都分配内存,通过该对象来访问这些实例变量,不同的实例变量是不同的。
类变量仅在生成第一个对象时分配内存,所有实例对象共享同一个类变量,每个实例对象对类变量的改变都会影响到其它的实例对象。类变量可通过类名直接访问,无需先生成一个实例对象,也可以通过实例对象访问类变量。

2) 实例方法和类方法
实例方法可以对当前对象的实例变量进行操作,也可以对类变量进行操作,实例方法由实例对象调用。
但类方法不能访问实例变量,只能访问类变量。类方法可以由类名直接调用,也可由实例对象进行调用。类方法中不能使用this或super关键字。

下面是关于实例成员和类成员的例子。

class Member
static int classVar;
int instanceVar;
static void setClassVar(int i)
classVar=i;
// instanceVar=i; // 类方法不能访问实例变量

static int getClassVar()
return classVar;
void setInstanceVar(int i)
classVar=i; //实例方法不但可以访问类变量,也可以实例变量
instanceVar=i;
int getInstanceVar( )
return instanceVar;

public class MemberTest
public static void main(String args[])
Member m1=new member();
Member m2=new member();
m1.setClassVar(1);
m2.setClassVar(2);
System.out.println("m1.classVar="+m1.getClassVar()+"
m2.ClassVar="+m2.getClassVar());
m1.setInstanceVar(11);
m2.setInstanceVar(22);
System.out.println("m1.InstanceVar="+m1.getInstanceVar
()+" m2.InstanceVar="+m2.getInstanceVar());



4.错误。native: 集成其它语言的代码
final 关键字
final 关键字可以修饰类、类的成员变量和成员方法,但final 的作用不同。

1) final 修饰成员变量:
final修饰变量,则成为常量,例如
final type variableName;
修饰成员变量时,定义时同时给出初始值,而修饰局部变量时不做要求。

2) final 修饰成员方法:
final修饰方法,则该方法不能被子类重写
final returnType methodName(paramList)



3) final 类:
final修饰类,则类不能被继承
final class finalClassName

参考技术A 1.可以
abstract 类就是抽象类,抽象类可以继承,必须重写里面的方法,但是不能被实例化,因为是残缺不全的~!
2.我在1里已经回答了,实例化就是创建一个实实在在存在的对象
3.static 变量 就是一个静态变量 只有一个副本就是 它是公用的一个变量,不会因为对象的创建而会成为某一个对象的一个成员变量
4.代码肯定是放在内存的code segement 那里的
final 方法就是一个方法被生命为final了 不能被重写,一个类如果被生命为final了 它就不能被其他的类继承 也就是不能有子类(断子绝孙的意思 哈哈)
//////回答完毕 谢谢//////////////
参考技术B 1.应该是不可以的,abstract是用于被扩展的,而final是不能被改写的··
2.正确 实例化也就是生成一个类对象的过程
3.正确 这个不好解释
4.错误,应该是native方法
参考技术C 1.一个abstract类可以被声明为final类( )
首先,抽象类里一般要有抽象的方法,抽象方法就是没有实现的方法。final 修饰符是定义一个类不能被继承,而抽象类和接口意义差不多,抽象类就是实现了部分方法的类,也是提供给外面继承或实现的,如果一个抽象类用<h1>final修饰了,那所有的类都不能继承这个抽象类了,那用abstract修饰就失去了意义。abstract与interface都还含有被别人实现的方法。具体的所abstract,interface与final修饰符号是互斥的。
2.一个abstract类不能被实例化( )
实例化是就是能有 new 创建一个实例对象。
3.一个static变量表明该变量只有一个副本( )
static变量,是一个静态修饰符,如果用static修饰,那么在程序加载一个对象的时候,就会自动将外部的static块加载进内存,称为一个类的共有属性。副本就是不能创建第二个 ,给上面结合,就应该明白为什么了把。也就是说static修饰的东西,不是固定的对象所有的,他是这个对象所有实例共有的
4.一个final方法使用非JAVA的其它语言实现,代码位于本地机上( )
首先,我不明白你的表述。final这个是修饰符,用来声明一个属性,对象等。标识这个东西是终态的。
如果修饰一个方法,说明这个方法不允许它的子类覆盖。
如果修饰一个变量,那么这个变量就不允许改变值了,成了一个常量、
如果修饰一个类,那么这个类是终态类,不允许被继承(extends)
final就是终态,最终的,你们谁都不能改变
参考技术D 1 abstract 是抽象类(抽象类是带有抽象方法的特殊类) 不可以被定义为final ,这里涉及到 final的作用,当final定义类的时候,其不可以有子类继承。如果不可以被继承,那么抽象类的抽象方法就没有办法被实现,所以不可以。
2 实例的意思就是在内存中生成一个对象。例如 new String(“”);
3 JAVA中 有常量 变量的定义。变量就是变化的,常量就是定义不能改变的,
static 说明是静态的,全局的意思。副本我的理解是作用域的意思把
4 当final 定义方法的时候,该方法不可以被重写。

有上网的时间多研究一下JAVA 教科书吧。
第5个回答  2008-11-09 看书自己学,书上都有,

你会这道阿里多线程面试题吗?

技术图片

背景

在前几天,群里有个群友问了我一道面试阿里的时候遇到的多线程题目,这个题目比较有意思,在这里和大家分享一下。

废话不多说,直接上题目:

通过N个线程顺序循环打印从0至100,如给定N=3则输出:

thread0: 0
thread1: 1
thread2: 2
thread0: 3
thread1: 4
.....

一些经常刷面试题的朋友,之前肯定遇到过下面这个题目:

两个线程交替打印0~100的奇偶数:
偶线程:0
奇线程:1
偶线程:2
奇线程:3

这两个题目看起来相似,第二个题目稍微来说比较简单一点,大家可以先思考一下两个线程奇偶数如何打印。

两线程奇偶数打印

有一些人这里可能会用讨巧的,用一个线程进行循环,在每次循环里面都会做是奇数还是偶数的判断,然后打印出这个我们想要的结果。在这里我们不过多讨论这种违背题目本意的做法。

其实要做这个题目我们就需要控制两个线程的执行顺序,偶线程执行完之后奇数线程执行,这个有点像通知机制,偶线程通知奇线程,奇线程再通知偶线程。而一看到通知/等待,立马就有朋友想到了Object中的wait和notify。没错,这里我们用wait和notify对其进行实现,代码如下:

public class 交替打印奇偶数 {
    static class SoulutionTask implements Runnable{
        static int value = 0;
        @Override
        public void run() {
            while (value <= 100){
                synchronized (SoulutionTask.class){
                    System.out.println(Thread.currentThread().getName() + ":" + value++);
                    SoulutionTask.class.notify();
                    try {
                        SoulutionTask.class.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    public static void main(String[] args) {
        new Thread(new SoulutionTask(), "偶数").start();
        new Thread(new SoulutionTask(), "奇数").start();
    }
}

这里我们有两个线程,通过notify和wait用来控制我们线程的执行,从而打印出我们目标的结果

N个线程循环打印

再回到我们最初的问题来,N个线程进行循环打印,这个问题我再帮助群友解答了之后,又再次把这个问题在群里面抛了出来,不少老司机之前看过交替打印奇偶数这道题目,于是马上做出了几个版本,让我们看看老司机1的代码:

public class 老司机1 implements Runnable {

    private static final Object LOCK = new Object();
    /**
     * 当前即将打印的数字
     */
    private static int current = 0;
    /**
     * 当前线程编号,从0开始
     */
    private int threadNo;
    /**
     * 线程数量
     */
    private int threadCount;
    /**
     * 打印的最大数值
     */
    private int maxInt;

    public 老司机1(int threadNo, int threadCount, int maxInt) {
        this.threadNo = threadNo;
        this.threadCount = threadCount;
        this.maxInt = maxInt;
    }

    @Override
    public void run() {
        while (true) {
            synchronized (LOCK) {
                // 判断是否轮到当前线程执行
                while (current % threadCount != threadNo) {
                    if (current > maxInt) {
                        break;
                    }
                    try {
                        // 如果不是,则当前线程进入wait
                        LOCK.wait();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                // 最大值跳出循环
                if (current > maxInt) {
                    break;
                }
                System.out.println("thread" + threadNo + " : " + current);
                current++;
                // 唤醒其他wait线程
                LOCK.notifyAll();
            }
        }
    }

    public static void main(String[] args) {
        int threadCount = 3;
        int max = 100;
        for (int i = 0; i < threadCount; i++) {
            new Thread(new 老司机1(i, threadCount, max)).start();
        }
    }
}

核心方法在run里面,可以看见和我们交替打印奇偶数原理差不多,这里将我们的notify改成了notifyAll,这里要注意一下很多人会将notifyAll理解成其他wait的线程全部都会执行,其实是错误的。这里只会将wait的线程解除当前wait状态,也叫作唤醒,由于我们这里用同步锁synchronized块包裹住,那么唤醒的线程会做会抢夺同步锁。

这个老司机的代码的确能跑通,但是有一个问题是什么呢?当我们线程数很大的时候,由于我们不确定唤醒的线程到底是否是下一个要执行的就有可能会出现抢到了锁但不该自己执行,然后又进入wait的情况,比如现在有100个线程,现在是第一个线程在执行,他执行完之后需要第二个线程执行,但是第100个线程抢到了,发现不是自己然后又进入wait,然后第99个线程抢到了,发现不是自己然后又进入wait,然后第98,97…直到第3个线程都抢到了,最后才到第二个线程抢到同步锁,这里就会白白的多执行很多过程,虽然最后能完成目标。
技术图片

还有其他老司机用lock/condition也实现了这样的功能,还有老司机用比较新颖的方法比如队列去做,当然这里就不多提了,大致的原理都是基于上面的,这里我说一下我的做法,在Java的多线程中提供了一些常用的同步器,在这个场景下比较适合于使用Semaphore,也就是信号量,我们上一个线程持有下一个线程的信号量,通过一个信号量数组将全部关联起来,代码如下:

static int result = 0;
    public static void main(String[] args) throws InterruptedException {
        int N = 3;
        Thread[] threads = new Thread[N];
        final Semaphore[] syncObjects = new Semaphore[N];
        for (int i = 0; i < N; i++) {
            syncObjects[i] = new Semaphore(1);
            if (i != N-1){
                syncObjects[i].acquire();
            }
        }
        for (int i = 0; i < N; i++) {
            final Semaphore lastSemphore = i == 0 ? syncObjects[N - 1] : syncObjects[i - 1];
            final Semaphore curSemphore = syncObjects[i];
            final int index = i;
            threads[i] = new Thread(new Runnable() {

                public void run() {
                    try {
                        while (true) {
                            lastSemphore.acquire();
                            System.out.println("thread" + index + ": " + result++);
                            if (result > 100){
                                System.exit(0);
                            }
                            curSemphore.release();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            });
            threads[i].start();
        }
    }

通过这种方式,我们就不会有白白唤醒的线程,每一个线程都按照我们所约定的顺序去执行,这其实也是面试官所需要考的地方,让每个线程的执行都能再你手中得到控制,这也可以验证你多线程知识是否牢固。

最后

最后这篇文章被我收录于JGrowing-Java面试篇,一个全面,优秀,由社区一起共建的Java学习路线,如果您想参与开源项目的维护,可以一起共建,github地址为:https://github.com/javagrowing/JGrowing (也可以直接点击阅读原文)。
麻烦给个小星星哟。

如果大家觉得这篇文章对你有帮助,你的关注和转发是对我最大的支持,O(∩_∩)O:

技术图片

以上是关于谁会这几个java判断题?的主要内容,如果未能解决你的问题,请参考以下文章

java如何判断一个类是不是实现了某个接口?

这几个事务案例会回滚吗?最后一个90%的人判断错了...

输入某年某月,判断该月有多少天,并判断是不是为闰年,谁会编这个程序

数字与数学7:幂的问题

这几个事务案例会回滚吗?最后一个90%的人判断错了...

这几个事务案例会回滚吗?最后一个90%的人判断错了...