Java编程思想笔记

文章目录


Java编程思想:

对象

1.1 Java单根结构有什么好处?

保证所有对象都有某些功能。可以很容易的在堆上创建,参数传递也容易很多。

使垃圾回收期的实现变得容易多。

1.2 Math.random和Random类有什么关系?

Math.random()内部调用的方法就是Random类中的nextDouble()

1.3 打印一个类的clas信息时,class [I是什么意思?

I表示基本类型int。

1.4 子类能通过super调用父类中的private方法吗?

不可以。

1.5 Java中除了static和final方法之外,其他的方法都是后期绑定吗?

是的。private方法也属于final方法。

将一个方法声明为final,可以防止其他人覆盖该方法,更重要的一点是,可以有效的关闭“动态绑定”。这样编译器可以生成更有效的代码,但实际上,这样做对程序整体性能并不会有什么改观。所以,最好根据设计来决定是否使用final,而不是为了提升性能。

1.5 为什么接口经常用作创建常量组的工具?

因为接口里的变量都是static和final的。JDK5以后有了enum,就没有必要再这么做了。

static和final定义的变量,一般变量名都用大写。

1.6 switch支持的类型?

Idea中如果输入适用的类型会有提示。

  • JDK5:char, byte, short or int
  • JDK7:char, byte, short, int, Character, Byte, Short, Integer, String, or an enum

1.7 compareTo返回1时,排在前面还是后面?

返回1表示当前对象大于比较对象,排在后面,也就是说默认升序。

1、为什么堆栈比堆快?

堆栈和堆都是位于RAM区域,主要区别在于堆栈是栈结构。

对于堆栈:

堆栈指针下移,会创建新的内存;若上移,就会释放那些内存。

因此,这是一种特别快的数据存储方式。

对于堆:

编译器不知道要从堆里分配多少空间,也不知道数据在堆里存在多久。

在堆里保存数据灵活,只需要用new,会在堆里自动进行数据的保存。

为了实现这种灵活性,必然付出代价:在堆里分配存储空间会花费更多的时间。

2、什么是静态存储?

静态(static)是指位于固定位置,也在RAM里。

程序运行期间,静态存储的数据将随时等候调用。

但,Java对象本身永远不会被置入静态存储空间。

3、Java数据类型有哪些,分别占几个字节?

8大类型,4211分类分别为,整型:byte,short,int,long;浮点型:float,double;字符型:char;布尔型:boolean。

整型字节分别是1,2,4,8个。浮点型4,8个,char型占2个字节,boolean占1个。

整型都有符号的。

主类型都有封装器。

4、如何表示高精度数字?

BigInteger和BigDecimal,两者没有主类型。

能对int或float做的事情,使用BigInteger和BigDecimal都能做,只是必须用方法调用,不能用运算符。

运算速度慢一些,但换来了精度。可以表示任意精度的整数或定点数字。

5、Java中是否允许在代码块内重新定义一个变量?

不允许。

例如,下面的代码会报错:

int x = 1;
{
    int x = 2;
}

6、Java对象超出作用域后会立刻消失么?

不会。对象的句柄会,对象不会,仍然占据着内存空间。

7、主类型默认值分别是什么?

整型都是0,long是0l(或L);float是0.0f(或F),double是0.0d(或D);char型是’\u0000’也就是null,布尔型是false。

8、局部变量有默认值吗,数组有默认值吗?

局部变量没有。

例如,在一个函数中存在以下代码将会报错:

int x;

数组内元素有默认值。

java和javaw

9、Idea里运行Java程序时启动的是哪个java进程?

JDK的bin目录里的java.exe

10、Jvisualvm运行时启动的是哪个java进程?

JDK下jre目录里的javaw.exe

11、java和javaw的区别?

java.exe是win32控制台应用,javaw.exe是win32GUI应用。

javaw.exe包括了java.exe的内容,并且添加了GUI界面,不启用控制台。

控制流程

13、Java存在短路吗?

存在。

例如,下面的test2()如果返回false,test3()将不再调用:

if(test1() && test2() && test3())

14、Java位运算符有哪些?

与:&;或:|;非:~;异或:^;

移位运算符:左移:<<,右移:>>,无符号右移:>>>

15、原码、反码和补码的概念,为什么要有反码,为什么要有补码,机器用什么码存储?

参考:https://blog.csdn.net/diaoda7872/article/details/101955089

概念:

  • 原码:正数的源码,反码和补码相同。
  • 反码:负数反码等于原码符号位不变,其他位取反。
  • 补码:负数补码等于其反码加1。

为什么要有反码:

机器只能做加法。如果计算机用原码存储和计算,会存在符号位也参与了运算的问题。

为什么要有补码:

反码解决了原码计算带来的符号位问题,但是存在+0和-0的问题。而补码不存在这个问题。

因此,机器用补码存储。

同时,由于使用补码不存在-0问题,int型的取值范围就是-2147483648-1和02147483647,-2147483648的原码就是原来的-0:10000000 00000000 00000000 00000000

举例:对于表达式 1-1=0,如果用原码计算,结果为-2,如果用反码计算结果为-0,而如果用补码计算,结果为0

16、int型的-1在内存中如何存储,-1 >>> 10 的结果是什么?

机器通过补码存储。

-1的源码:10000000 00000000 00000000 00000001

-1的补码:11111111 11111111 11111111 11111111

-1 >>> 10后的补码:00000000 00111111 11111111 11111111

该补码符号位是0,是个正数,原码和补码相同,结果为:4194303

17、short和byte型可以右移和左移吗?

若对byte或short值进行无符号右移位运算,得到的可能不是正确的结果。它们会自动转换成int类型,并进行右移位。但“零扩展”不会发生,所以在那些情况下会得到-1的结果

short或byte可以正常进行有符号右移和左移。

18、Java中 1.39e-47f 表示什么意思?

C++,Java中,e都代表10的几次幂。

1.39e-47f 表示 1.39 x 10的-47次方

19、float类型末尾可以不加f吗?

long类型和double末尾的l可以不写,但是float不行。

如果不写f,默认会认为是double类型,编译器会提示你将double转为float。

20、为什么Java没有sizeof?

C或C++中,sizeof能够获知数据分配的字符数量。它最常见的应用就是移植。不同的数据在不同的机器上可能有不同的大小。

例如,一台计算机可用32 位来保存整数,而另一台只用 16 位保存。显然,在第一台机器中,程序可保存更大的值。

而Java不需要sizeof,因为Java不需要考虑移植问题,Java本身与平台无关,数据类型在任何机器都是一样的。

21、Math.random()的范围是什么?

[0,1)

初始化和清除

22、Java的finalize方法什么时候会被调用,作用是什么,调用顺序是什么?

gc时调用。但调用后只有在下一次垃圾收集过程中,才会真正回收对象的内存

作用:

可以在垃圾收集期间进行一些重要的清除工作。

之所以要使用finalize(),是由于有时需要采取与Java 的普通方法不同的一种方法,通过分配内存来做一些具有 C 风格的事情。

这主要可以通过“固有方法”来进行,它是从Java 里调用非 Java 方法的一种方式。

调用顺序:

  • 成员对象按照与它们创建时相同的顺序进行收尾
  • 继承类对象按照初始化顺序相反的顺序进行收尾,先子类调用finalize再父类调用

23、Java对象成员变量的初始化顺序?

初始化顺序为从上到下

成员变量 > 构造器

static成员变量和static代码块只有在对象首次创建的时候调用,并且只调用一次。

main方法所在的类的static成员变量最先初始化。

24、static初始化发生在什么时候?

static 初始化仅发生一次,在 Class 对象首次载入的时候。

访问修饰符

25、Java访问修饰符有哪些?

  • public:任何地方可以访问
  • protected:子类访问
  • friendly:友好的,同一个包内可以访问,不需要导入
  • private:私有

26、Java文件中必须要有一个public的类吗?

不必须。

如果类不用public修饰,使用这个包时,将不能通过import引入并使用这个类。

例如,类库如果不想向外部暴露一个类,可以不加public。

多形性

27、final修饰的对象不可变吗?

修饰基础数据类型不可变,如果是对象,对象的引用不可变,内部是可以变的,包括数组。

28、final有什么好处?

可以有效地关闭动态绑定,生成效率更高的代码。

什么是绑定:

将一个方法和调用主题联系到一起就叫绑定。

动态绑定:

也叫后期绑定,或者运行期绑定。编译器不知道对象的类型,但方法调用机制能自己去调查,找到正确的方法主体。

29、接口的数据默认是什么类型的?

默认都是static和final类型。

30、接口可以用作enum吗?

可以。由于接口的字段都有static和final属性,所以可以进行常数分组,和enum有相同的效果。

举例:

public interface Months {
    int
    JANUARY = 1, FEBRUARY = 2, MARCH = 3, 
    APRIL = 4, MAY = 5, JUNE = 6, JULY = 7, 
    AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10,
    NOVEMBER = 11, DECEMBER = 12;
}

如果用类来实现这个效果:

public final class Month2 {
    private String name;

    private Month2(String nm) {
        name = nm;
    }

    public String toString() {
        return name;
    }

    public final static Month2
            JAN = new Month2("January"),
            FEB = new Month2("February"),
            MAR = new Month2("March"),
            APR = new Month2("April"),
            MAY = new Month2("May"),
            JUN = new Month2("June"),
            JUL = new Month2("July"),
            AUG = new Month2("August"),
            SEP = new Month2("September"),
            OCT = new Month2("October"),
            NOV = new Month2("November"),
            DEC = new Month2("December");
    public final static Month2[] month = {
            JAN, JAN, FEB, MAR, APR, MAY, JUN,
            JUL, AUG, SEP, OCT, NOV, DEC
    };

    public static void main(String[] args) {
        Month2 m = Month2.JAN;
        System.out.println(m);
        m = Month2.month[12];
        System.out.println(m);
        System.out.println(m == Month2.DEC);
        System.out.println(m.equals(Month2.DEC));
    }
}

类声明为final,不允许继承。并在类内创建好static和finla类型的该类的对象。

内部类

31、内部类有什么作用?

要解决一个复杂的问题,并希望创建一个类,用来辅助自己的程序方案。同时不愿意把它公开。

在控制框架(例如事件驱动模型框架)中会经常使用内部类。

32、方法或作用于内可以创建内部类吗?

可以。方法内可以使用class定义一个类,也可以直接 new 接口名(){具体实现} 实现一个接口,创建一个匿名类。

33、内部类对外部类的访问权限如何?

内部类拥有对封装类所有元素的访问权限。

必须记住内部类的对象默认持有创建它的那个封装类的一个对象的句柄,而封装类的作用就是创建这个内部类。

举例:

可以使用Sequence.this访问外部类对象成员。

如果没有提供getSelector()这样获取内部类对象的方法,外部类对象可以使用Sequence.SSelector ss = s.new SSelector()的方式创建内部类对象。

interface Selector {
    boolean end();
    Object current();
    void next();
}
public class Sequence {
    private Object[] o;
    private int next = 0;
    public Sequence(int size) {
        o = new Object[size];
    }
    public void add(Object x) {
        if(next < o.length) {
            o[next] = x;
            next++;
        }
    }
    private class SSelector implements Selector {
        int i = 0;
        public boolean end() {
            return i == o.length;
        }
        public Object current() {
            return o[i];
        }
        public void next() {
            if(i < o.length) i++;
        }
    }
    public Selector getSelector() {
        return new SSelector();
    }
    public static void main(String[] args) {
        Sequence s = new Sequence(10);
        for(int i = 0; i < 10; i++)
            s.add(Integer.toString(i));
        Selector sl = s.getSelector();
        while(!sl.end()) {
            System.out.println((String)sl.current());
            sl.next();
        }
    }
}

34、static内部类有哪些限制?

  • 为创建一个 static 内部类的对象,我们不需要一个外部类对象
  • 不能从 static 内部类的一个对象中访问一个外部类对象
  • 内部类不可拥有static 数据或static 内部类

35、什么时候用static内部类?

除非已拥有外部类的一个对象,否则不可能创建内部类的一个对象。这是由于内部类的对象已同创建它的外部类的对象“默默”地连接到一起。倘若为了创建内部类的对象而不需要创建外部类的一个对象,那么可将所有东西都设为static。为了能正常工作,同时也必须将内部类设为static。

举例:

abstract class Contents {
    abstract public int value();
}
interface Destination {
    String readLabel();
}
public class Parcel10 {
    private static class PContents
            extends Contents {
        private int i = 11;
        public int value() { return i; }
    }
    protected static class PDestination
            implements Destination {
        private String label;
        private PDestination(String whereTo) {
            label = whereTo;
        }
        public String readLabel() { return label; }
    }
    public static Destination dest(String s) {
        return new PDestination(s);
    }
    public static Contents cont() {
        return new PContents();
    }
    public static void main(String[] args) {
        Contents c = cont();
        Destination d = dest("Tanzania");
    }
}

36、接口里可以创建static内部类吗?

可以。

由于类是“静态”的,所以它不会违反接口的规则,static 内部类只位于接口的命名空间内部

举例:

interface IInterface {
    static class Inner {
        int i, j, k;
        public Inner() {}
        void f() {}
    }
}

37、内部类在编译时(build)也会生成单独的一个class文件吗?

是的,但是文件名格式为 封装类类名$内部类类名.class

38、什么是应用程序框架?

指一系列类,它们专门设计用来解决特定类型的问题。

我们可从一个或多个类继承,并覆盖其中的部分方法。我们在覆盖方法中编写的代码用于定制由那些应用程序框架提供的常规方案,以便解决自己的实际问题。

39、判断以下代码输出,理解初始化顺序

abstract class Glyph {
    abstract void draw();
    Glyph() {
        System.out.println("Glyph() before draw()");
        draw();
        System.out.println("Glyph() after draw()");
    }
}
class RoundGlyph extends Glyph {
    int radius = 1;
    RoundGlyph(int r) {
        radius = r;
        System.out.println(
                "RoundGlyph.RoundGlyph(), radius = "
                        + radius);
    }
    void draw() {
        System.out.println(
                "RoundGlyph.draw(), radius = " + radius);
    }
}
public class PolyConstructors {
    public static void main(String[] args) {
        new RoundGlyph(5);
    }
}

结果:

Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5

为什么第二行会输出radius=0而不是1?

初始化的实际过程是这样的:

(1) 在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零。
(2) 就象前面叙述的那样,调用基础类构建器。此时,被覆盖的draw()方法会得到调用(的确是在RoundGlyph 构建器调用之前),此时会发现 radius 的值为 0,这是由于步骤(1)造成的。
(3) 按照原先声明的顺序调用成员初始化代码。
(4) 调用衍生类构建器的主体。

从逻辑的角度说,我们似乎已进行了无懈可击的设计,所以它的错误行为令人非常不可思议。而且没有从编译器那里收到任何报错信息(C++在这种情况下会表现出更合理的行为)。象这样的错误会很轻易地被人忽略,而且要花很长的时间才能找出。

因此,设计构建器时一个特别有效的规则是:用尽可能简单的方法使对象进入就绪状态;如果可能,避免调用任何方法。在构建器内唯一能够安全调用的是在基础类中具有final 属性的那些方法(也适用于private方法,它们自动具有final 属性)。这些方法不能被覆盖,所以不会出现上述潜在的问题。

集合

40、Java1.1开始提供的集合类有哪些,缺点是什么?

  • Vector:矢量
  • BisSet:位集
  • Stack:栈
  • HashTable:散列表

缺点:元素都是Object类型,类型未知,丢失了类型信息,因此,类型不安全。任何人都可以把一条狗扔进来。

例如:

for(int i = 0; i < 7; i++)
    cats.addElement(new Cat(i));
cats.addElement(new Dog(7));
for(int i = 0; i < cats.size(); i++)
    ((Cat)cats.elementAt(i)).print();

虽然可以通过强转类型为Cat,但是如果丢了只狗进去,运行时就会报错。

41、封装器的值可以改变吗?

不可以。例如Integer,内部的int型的value是final类型。

42、使用HashMap或HashTable时,如何让两个对象的键相同?

同时覆写hashcode方法和equals方法。

43、添加到HashSet里的对象需要实现什么?

需要重写hashcode方法和equals方法。对于TreeMap,还需要实现comparable接口。

44、Arrays.toList()产生的List可变吗?

不可以。该列表是由一个固定长度的数组后推出来的。因此唯一能够支持的就是那些不改变数组长度的操作。否则,将产生 UnsupportedOperationException异常。

45、使用Arrays.sort或者Arrays.binarySearch有什么条件?

要比较的对象是可比较的。自身是实现了Comparable接口的可比较类,或者提供一个实现了Comparator接口的比较器。

46、Arrays 类作用?

为所有基本数据类型的数组提供了一个过载的 sort()和 binarySearch()以及其他适用于数组的方法,它们亦可用于String 和Object。对于Object,需要自己提供比较器。

47、Collections和Arrays有什么区别?

Collections里的方法的用法与在Arrays 中的用法是完全一致的,只是用一个列表代替了数组。

例如,Collections里也有针对于列表的sort和binarySearch方法。

48、ArrayList使用普通for循环和增强for循环会导致ConcurrentModificationException吗?

普通for循环不会,但是也不好,比如如果for循环并进行if判断然后删除某个元素,当前元素的下个元素会跳过判断。

增项for循环或使用Iterator会导致ConcurrentModificationException。

异常

51、Exception类的getMessage()、toString()和printStackTrace()有什么区别?

一个是自定义的异常信息,一个是异常类型+异常信息,一个是异常的方法调用栈。

public static void main(String[] args) {
        try {
            throw new Exception("Here's my Exception");
        } catch(Exception e) {
            System.out.println("Caught Exception");
            System.out.println(
                    "e.getMessage(): " + e.getMessage());
            System.out.println(
                    "e.toString(): " + e.toString());
            System.out.println("e.printStackTrace():");
            e.printStackTrace();
        }
    }

结果:

Caught Exception
e.getMessage(): null
e.toString(): java.lang.Exception
e.printStackTrace():
java.lang.Exception
	at com.fengsw.exception.ExceptionMethods.main(ExceptionMethods.java:9)

52、Throwable的子类有什么?

Exception和Error。

53、RuntimeException和其他异常相比有什么特殊性?

没必要指出一个方法throws RuntimeException,因为已经假定可能出现那种情况。

RuntimeException用于指出编程中的错误,所以几乎永远不必专门捕获一个RuntimeException。它在默认情况下会自动得到处理。若必须检查 RuntimeException,我们的代码就会变得相当繁复。

假若一个RuntimeException 获得到达main()的所有途径,同时不被捕获,那么当程序退出时,会为那个违例调用 printStackTrace()。

RuntimeException 在此时代表一个编程错误。 一个我们不能捕获的错误(例如,由客户程序员接收传递给自己方法的一个空句柄)。

54、父类的方法没有抛出异常,子类覆写的方法可以抛出异常吗?

不可以。

并且,如果父类抛出了异常A,子类如果要抛出异常,异常必须是A的子异常。

55、判断catch和finally的执行顺序?

public static void main(String[] args) {
        System.out.println(
                "Entering first try block");
        try {
            System.out.println(
                    "Entering second try block");
            try {
                throw new Ex();
            } finally {
                System.out.println(
                        "finally in 2nd try block");
            }
        } catch(Ex e) {
            System.out.println(
                    "Caught Ex in first try block");
        } finally {
            System.out.println(
                    "finally in 1st try block");
        }
    }

结果:

Entering first try block
Entering second try block
finally in 2nd try block
Caught Ex in first try block
finally in 1st try block

结论:即使异常不在当前的catch 从句集里捕获,finally 都会在异常控制机制转到更高级别搜索一个控制器之前得以执行。

IO

56、InputStream的输入源有哪些?

  • 字节数组
  • String对象
  • 文件
  • 管道
  • 其他流
  • 其他起源地,比如Internet连接

57、InputStream有哪些类型?

  • ByteArrayInputStream:允许内存中的一个缓冲区作为InputStream 使用 从中提取字节的缓冲区/作为一个数据源使用。通过将其同一个 FilterInputStream 对象连接,可提供一个有用的接口。
  • StringBufferInputStream:已废弃。the preferred way to create a stream from a string is via the StringReader class.
  • FilterInputStream:
  • PipedInputString
  • SequenceInputStream
  • FilterInputStream
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值