文档章节

一.java随记笔记(备复习面试用)

1024菜bird
 1024菜bird
发布于 2016/10/10 09:22
字数 3525
阅读 44
收藏 0

一.java静态方法只能调用静态方法 

1.需要知道java的编译过程。静态方法的代码在项目启动的时候就被初始化,那么,你“主方法”是静态的,项目启动时需要初始化,“被调用的方法”当然也必须是静态的,因为在“主方法”初始化的时候需要调用到“被调用的方法”,否则就无法找到“被调用方法”而导致编译失败。 如果你在非静态的方法去调用其他的方法,那么”被调用的方法“就不需要是静态的了

二.Java类在new的过程中,静态域、静态块、非静态域、非静态块、构造函数的执行顺序问题

1.这里先把整理好的结论抛给大家,代码实例验证请点击连接https://my.oschina.net/u/1054538/blog/756146。在Java类被new的过程中,执行顺序如下:

  •     实现自身的静态属性和静态代码块。(根据代码出现的顺序决定谁先执行)
  •     实现自身的非静态属性和非静态代码块。
  •     执行自身的构造函数。

    在实现继承的类被new的过程中,初始化执行顺序如下:

  •     实现父类的公共静态属性和静态块级代码。
  •     实现自身的静态属性和静态块级代码。
  •     实现父类的非静态属性和非静态代码块。
  •     执行父类的构造函数。
  •     实现自身的非静态属性和非静态代码块。
  •     执行自身的构造函数。

三.final的对象引用

使用final的限制条件和局限性

 当声明一个final成员时,必须在构造函数退出前设置它的值,如下:

public class MyClass {
  private final int myField = 3;
  public MyClass() {
    ...
  }
}

或者

public class MyClass {
  private final int myField;
  public MyClass() {
    ...
    myField = 3;
    ...
  }
}

final关键字作用在对象上,指的是该对象(堆)的引用(栈)不可变非对象不可变,也就是说该引用不能指向其他对象

需要强调的是将指向对象的成员声明为final只能将该引用设为不可变的,而非所指的对象。例如如果一个list声明如下:

private final List myList = new ArrayList();

仍然可以修改该list

myList.add("Hello");

然而,声明为final可以保证如下操作不合法:

myList = new ArrayList();
myList = someOtherList;

什么时候应该使用final

在匿名内部类中引用外部对象要加final修饰符呢,因为,在匿名内部类中引用的外部对象受到外部线程的作用域的制约有其特定的生命周期,
      以线程为例,当外部的变量生命周期已经完结之后,内部的线程还在运行,怎么样解决这个外部生命周期已经结束而在内部却需要继续使用呢,
      这个时候就需要在外部变量中添加final修饰符,其实内部匿名类使用的这个变量就是外部变量的一个“复制品”,即使外部变量生命周期已经结束,内部的“复制品“依然可用。

 一个答案就是“尽可能的使用”。任何你不希望改变的(基本类型,或者指向一个对象,不管该对象是否可变)一般来讲都应该声明为final。另一种看待此问题的方式是:

 如果一个对象将会在多个线程中访问并且你并没有将其成员声明为final,则必须提供其他方式保证线程安全

  “其他方式”可以包括声明成员为volatile,使用synchronized或者显式Lock控制所有该成员的访问。

四.基本数据类型

java中基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean。

这5种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象。 两种浮点数类型的包装类Float,Double并没有实现常量池技术。

1.Integer

byte(字节) 	    8         -128 - 127                                           0
shot(短整型)        16      -32768 - 32768                                         0
int(整型)           32   -2147483648-2147483648                                    0
long(长整型)        64   -9233372036854477808-9233372036854477808                  0        
float(浮点型)       32  -3.40292347E+38-3.40292347E+38                            0.0f
double(双精度)	    64  -1.79769313486231570E+308-1.79769313486231570E+308        0.0d
char(字符型)        16         ‘ \u0000 - u\ffff ’                             ‘\u0000 ’
boolean(布尔型)     1         true/false                                         false

        Integer a=100,b=100;
        System.out.println(a==b);//true
        Integer aa=128,bb=-128;
        System.out.println(aa==bb);//false

JVM会自动维护八种基本类型的常量池,int常量池中初始化-128~127的范围,所以当为Integer i=127时,在自动装箱过程中是取自常量池中的数值,而当Integer i=128时,128不在常量池范围内,所以在自动装箱过程中需new 128,所以地址不一样。

java除了基本数据类型可以直接用运算符==来比较变量的值以外,其他类型(类,包括外覆类)声明的对象如果相比较值或内容是否相等,都必须用equals,如果用==,比较的是对象引用在内存中的地址值,而不是对象引用的内容。

2.String

针对同一个对象,new出来的字符串和直接赋值给变量的字符串存放的位置是不一样的,前者是在堆里面,而后者在常量池里面,另外,在做字符串拼接操作,也就是字符串相"+"的时候,得出的结果是存在在常量池或者堆里面,这个是根据情况不同不一定的,我写了几行代码测试了一下。

    1.直接定义字符串变量的时候赋值,如果表达式右边只有字符串常量,那么就是把变量存放在常量池里面。

  2.new出来的字符串是存放在堆里面。

  3.对字符串进行拼接操作,也就是做"+"运算的时候,分2中情况:

  i.表达式右边是纯字符串常量,那么存放在栈里面。

  ii.表达式右边如果存在字符串引用,也就是字符串对象的句柄,那么就存放在堆里面。

       String str1 = "aaa";
        String str2 = "bbb";
        String str3 = "aaabbb";
        String str4 = str1 + str2;
        String str5 = "aaa" + "bbb";
        System.out.println(str3 == str4); // false
        System.out.println(str3 == str4.intern()); // true
        System.out.println(str3 == str5);// true

String类的intern()方法的作用

一般我们变成很少使用到 intern这个方法,今天我就来解释一下这个方法是干什么的,做什么用的

首先请大家看一个例子:

    public static void main(String[] args) throws Exception {
        String a =  "b" ; 
        String b =  "b" ; 
        
        System.out.print( a == b); 
        
        String c = "d" ;
        String d = new String( "d" ).intern() ; 
        System.out.println( c == d);
    } 

大家能看出来这个例子打印在控制台的消息吗?在这里控制台输出的结果都是true  true,原因在于 intern 这个方法返回的是 返回字符串对象的规范化表示形式,当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。这时候c和d就是相等的。

        String s1 = "ab123" ;
        String s2 = new String( "ab123" ) ;
        System.out.println( s1 == s2 ); 
        String s3 = s2.intern() ; 
        System.out.println( s1 == s3 ) ; 

public static final String A;   // 常量A
public static final String B;  // 常量B
    public static void main (String [] args) {
            // 将两个常量用+连接对s进行初始化 
            String s = A + B; 
            String t = "abcd"; 
            if (s == t) { 
                System.out.println("s等于t,它们是同一个对象"); 
                } 
            else { 
                System.out.println("s不等于t,它们不是同一个对象"); 
                } 
        //scheduledThreadPool();
    }
    static { A = "ab"; B = "cd"; } 

解释:

s不等于t,它们不是同一个对象。

A和B虽然被定义为常量,但是它们都没有马上被赋值。在运算出s的值之前,他们何时被赋值,以及被赋予什么样的值,都是个变数。因此A和B在被赋值之前,性质类似于一个变量。那么s就不能在编译期被确定,而只能在运行时被创建了。

如果改成:

public static final String A = "ab"; 
    // 常量A
 public static final String B = "cd"; 

结果为:s等于t,它们是同一个对象

String s1 = new String("xyz"); //创建了几个对象?

解释:

考虑类加载阶段和实际执行时。

(1)类加载对一个类只会进行一次。”xyz”在类加载时就已经创建并驻留了(如果该类被加载之前已经有”xyz”字符串被驻留过则不需要重复创建用于驻留的”xyz”实例)。驻留的字符串是放在全局共享的字符串常量池中的。

(2)在这段代码后续被运行的时候,”xyz”字面量对应的String实例已经固定了,不会再被重复创建。所以这段代码将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s1 持有。

这条语句创建了2个对象。

 

public class TestStringEqual {
    public static void main(String[] args) {
        String hello = "Hello";
        String lo = "lo";
        System.out.println((hello == "Hello") + " "); //true
        System.out.println((Other.hello == hello) + " "); //true
        System.out.println((other.Other.hello == hello) + " "); //true
        System.out.println((hello == ("Hel"+"lo")) + " "); //true
        System.out.println((hello == ("Hel"+lo)) + " "); //false
        System.out.println(hello == ("Hel"+lo).intern()); //true}}
        
    }
}
class Other {
    static String hello = "Hello";
}

package other;
public class Other {
    public static String hello = "Hello";
}

解释:

在同包同类下,引用自同一String对象.

在同包不同类下,引用自同一String对象.

在不同包不同类下,依然引用自同一String对象.

在编译成.class时能够识别为同一字符串的,自动优化成常量,引用自同一String对象.

在运行时创建的字符串具有独立的内存地址,所以不引用自同一String对象.

3.Float类型 减法运算时精度丢失问题

   Float xx = 2.0f;
   Float yy = 1.8f;
   Float tt = xx - yy;
   System.out.println("tttttt-----" + tt);

果然输出结果是: tttttt-----0.20000005

测试了几个float类型的减法,除了*.0这样的相减没有异议之外,都存在这个问题,就是说float在相减的时候精度丢失了。后来在网上找到一段解决这个问题的办法,记在这里:

   Float xx = 2.2f;
   Float yy = 2.0f;
   Float tt = xx - yy;
  
   BigDecimal b1 = new BigDecimal(Float.toString(xx));
   BigDecimal b2 = new BigDecimal(Float.toString(yy));
   float ss = b1.subtract(b2).floatValue(); 
   System.out.println("ssss----" + ss);
   System.out.println("tttttt-----" + tt);

ssss----0.2
tttttt-----0.20000005

这样一对比,差异就很明显了。

解决了问题,再找了一下为什么会产生这种差异:

网上有篇文章写得很详细,标题为《剖析float型的内存存储和精度丢失问题》,全文内容如下:

问题提出:12.0f-11.9f=0.10000038,"减不尽"为什么?

现在我们就详细剖析一下浮点型运算为什么会造成精度丢失?

http://blog.csdn.net/fancylovejava/article/details/12027039

五:if里填什么能能输出ab   if(){
           System.out.println("a");
        }else{
           System.out.println("b");
        }

联想Java中print、printf、println的区别

printf主要是继承了C语言的printf的一些特性,可以进行格式化输出
print就是一般的标准输出,但是不换行
println和print基本没什么差别,就是最后会换行
System.out.printf("the number is: d",t);

参照JAVA API的定义如下:
'd' 整数 结果被格式化为十进制整数
'o' 整数 结果被格式化为八进制整数
'x', 'X' 整数 结果被格式化为十六进制整数
'e', 'E' 浮点 结果被格式化为用计算机科学记数法表示的十进制数
'f' 浮点 结果被格式化为十进制数
'g', 'G' 浮点 根据精度和舍入运算后的值,使用计算机科学记数形式或十进制格式对结果进行格式化。
'a', 'A' 浮点 结果被格式化为带有效位数和指数的十六进制浮点数
println("test")相当于print("testn")就是一般的输出字符串

printprintlnprintf的区别
print将它的参数显示在命令窗口,并将输出光标定位在所显示的最后一个字符之后。
println 将它的参数显示在命令窗口,并在结尾加上换行符,将输出光标定位在下一行的开始。
printf是格式化输出的形式。

 int i = 4;
   double j = 5;

   System.out.print("用print输出i:"+ i);
   System.out.println( "用println输出i:"+ i);
   System.out.printf("i的值为%d,j的值为%f", i,j);

 

用print输出i:4用println输出i:4
i的值为4,j的值为5.000000

可以看到,用print输出i后,没有换行,用println输出的结果直接在print输出语句后面,而输出println后换行了,所以用printf输出时,在第二行

我们再来看printf
“i的值为%d,j的值为%f”这个字符串中的"%d"变为i的值了,而"%f"变为了j的值了!
这里,"%d"的意思是一个int值的占位符,"%f"为一个double 或float值的点位符,这个变量的参数在后面提供。注意的是实参名必须按顺序排。不然就会错了。而且类型也要相符。如果我们把语句改为System.out.printf("i的值为%d,j的值为%f", j,i);//i和j位置反了
这时就有错了因为"%d"对应的参数变为j,"%f"对应的变为i了,而j是double的,与"%d"是int形的不一致。所以有错了。
还有"%s"是一个字符串值的点位符的意思。"%c"是一个字符值的点位符的意思。
可能读者还会问为什么j输出变成了5.000000?那是因为double是默认有6位小数的(这个可能和系统电脑有关,有的不是6位吧)但是如果你想只要输出两位小数行不行?可以啊!只要改下语句就行了!
System.out.printf("i的值为%d,j的值为%.2f", i,j);
这里的"%.2f"的意思是输出两位小数点。如果想输出三位那就"%.3f"。
说到这里你会发现原来printf也很有用的。这样可以控制输出的格式。

 

© 著作权归作者所有

1024菜bird
粉丝 77
博文 141
码字总数 138266
作品 0
海淀
程序员
私信 提问
复习 2 个月拿下大厂 Offer,Java 面试指南带你通关跳槽季

作者 | 码匠笔记 责编 | 仲培艺 去年的这个时候,笔者通过两个月的复习拿到了阿里巴巴的 Offer,有一些运气,也有一些心得,借着跳槽季来临特此分享出来。本文既是复习思路,亦可当做学习思路...

CSDN资讯
02/16
0
0
【Java面试复习经典】传智播客Java就业班入学测试题及答案解析(2014年版)

【Java面试复习经典】传智播客Java就业班入学测试题及答案解析(2014年版)   共50道题,每道题2分,总分100分,80分为合格。   注意,题目有多选,也有单选。请认真作答。 ==============...

黑泽明军
2018/04/12
0
0
【Java面试复习经典】传智播客Java就业班入学测试题及答案解析(2012年版)

【Java面试复习经典】传智播客Java就业班入学测试题及答案解析(2012年版)   共50道题,每道题2分,总分100分,80分为合格。   注意,题目有多选,也有单选。请认真作答。 ==============...

黑泽明军
2018/04/12
0
0
BAT等大厂Android面试书单和知识点清单

java是Android开发的基础,在BAT的初面中,会涉及到比较多的java基础知识,所以比较重要,下面我介绍的书籍内容是由浅到深。 1.Thinking in java:这本书被称为Java的三大圣经之一,虽然书比...

android自学
2018/07/25
0
0
阿里最新Java研发工程师面试经验(社招)

前言 今天要和大家一起分享的是一位面试菜鸟网络的Java研发工程师的面试经验,他通过了前三次电话面试,但是在第四次现场面试中没有能够成功通过,最终遗憾地与菜鸟的Offer说再见。但是正如这...

Java-飞鱼
09/06
109
0

没有更多内容

加载失败,请刷新页面

加载更多

Qt程序打包发布方法(使用官方提供的windeployqt工具)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/toTheUnknown/article/details/81748179 如果使用到了Qt ...

shzwork
40分钟前
7
0
MainThreadSupport

MainThreadSupport EventBus 3.0 中的代码片段. org.greenrobot.eventbus.MainThreadSupport 定义一个接口,并给出默认实现类. 调用者可以在EventBus的构建者中替换该实现. public interface ...

马湖村第九后羿
今天
3
0
指定要使用的形状来代替文字的显示

控制手机键盘弹出的功能只能在ios上实现,安卓是实现不了的,所以安卓只能使用type类型来控制键盘类型,例如你要弹出数字键盘就使用type="number",如果要弹出电话键盘就使用type="tel",但这...

前端老手
今天
6
0
总结:Raft协议

一、Raft协议是什么? 分布式一致性算法。即解决分布式系统中各个副本数据一致性问题。 二、Raft的日志广播过程 发送日志到所有Followers(Raft中将非Leader节点称为Follower)。 Followers收...

浮躁的码农
今天
7
0
Flask-admin Model View字段介绍

Model View字段介绍 can_create = True 是否可以创建can_edit = True 是否可以编辑can_delete = True 是否可以删除list_template = 'admin/model/list.html' 修改显......

dillonxiao
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部