天道酬勤,学无止境

Java关键字介绍之final

总结关键字final的用法。

author: ZJ 07-3-16
Blog: [url]http://zhangjunhd.blog.51cto.com/[/url]


Java中声明属性、方法和类时,可使用关键字final来修饰。final变量即为常量,只能赋值一次;final方法不能被子类重写;final类不能被继承。

1final成员

声明 final 字段有助于优化器作出更好的优化决定,因为如果编译器知道字段的值不会更改,那么它能安全地在寄存器中高速缓存该值。final 字段还通过让编译器强制该字段为只读来提供额外的安全级别。

 

1.1关于final成员赋值

1)在java中,普通变量可默认初始化。但是final类型的变量必须显式地初始化。

 

2final 成员能且只能被初始化一次。

 

3final成员必须在声明时(在final变量定义时直接给其赋值)或者在构造函数中被初始化,而不能在其它的地方被初始化。
示例1 Bat.java

public class Bat {

    final double PI = 3.14; // 在定义时赋值

    final int i; // 因为要在构造函数中进行初始化所以此处便不可再赋值

    final List<Bat> list; // 因为要在构造函数中进行初始化所以此处便不可再赋值

 

    Bat() {

       i = 100;

       list = new LinkedList<Bat>();

    }

 

    Bat(int ii, List<Bat> l) {

       i = ii;

       list = l;

    }

 

    public static void main(String[] args) {

       Bat b = new Bat();

       b.list.add(new Bat());

       // b.i=25;

       // b.list=new ArrayList<Bat>();

       System.out.println("I=" + b.i + " List Type:" + b.list.getClass());

       b = new Bat(23, new ArrayList<Bat>());

       b.list.add(new Bat());

       System.out.println("I=" + b.i + " List Type:" + b.list.getClass());

    }

}

 

结果:

I=100 List Type:class java.util.LinkedList

I=23 List Type:class java.util.ArrayList

 

main方法中有两行语句注释掉了,如果你去掉注释,程序便无法通过编译,这便是说,不论是i的值或是list的类型,一旦初始化,确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型。

 

1.2 final引用字段的无效初始化

要正确使用final字段有点麻烦,对于其构造子能抛出异常的对象引用来说尤其如此。因为 final 字段在每个构造器中必须只初始化一次,如果 final 对象引用的构造器可能抛出异常,编译器可能会报错,说该字段没有被初始化。编译器一般比较智能化,足以发现在两个互斥代码分支(比如,if...else 块)的每个分支中的初始化恰好只进行了一次,但是它对 try...catch 块通常不会如此“宽容”。
下面这段代码通常会出现问题。
class Thingie {

    public static Thingie getDefaultThingie() {

       return new Thingie();

    }

}

 

public class Foo {

    private final Thingie thingie;

 

    public Foo() {

       try {

           thingie = new Thingie();

       } catch (Exception e) {

           thingie = Thingie.getDefaultThingie();//Error:The final field thingie may already have been assigned

       }

    }

}

 

你可以这样修改。
public class Foo {

    private final Thingie thingie;

 

    public Foo() {

       Thingie tempThingie;

       try {

           tempThingie = new Thingie();

       } catch (Exception e) {

           tempThingie = Thingie.getDefaultThingie();

       }

       thingie = tempThingie;

    }

}

 

1.3关于final成员使用

当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引用不可再变。然而,对象其本身却是可以被修改的,Java并未提供使任何对象恒定不变的途径。这一限制同样适合数组,它也是对象。
示例2

private final int VAL_ONE=9;

private static final int VAL_TWO=99;

public static final int VAL_THREE=999;
由于VAL_ONE VAL_TOW 是带有编译期数值的final 原始类型,所以它们二者均可以用作编译期常量,并且没有重大区别。VAL_THREE是一种更加典型的对常量进行定义的方式:定义为 public,则可以被用于包之外;定义为 static 来强调只有一份;定义为 final 来说明它是一个常量。
final标记的变量即成为常量,但这个常量也只能在这个类的内部使用,不能在类的外部直接使用。但是当我们用public static final 共同标记常量时,这个常量就成为全局的常量(一个既是static又是final的字段只占据一段不能改变的存储空间)。而且这样定义的常量只能在定义时赋值,其他地方都不行。
示例3

class Value {

    int i;

 

    public Value(int i) {

       this.i = i;

    }

}

 

public class FinalData {

    private static Random rand = new Random();

 

    private String id;

 

    public FinalData(String id) {

       this.id = id;

    }

 

    private final int i4 = rand.nextInt(20);

 

    static final int i5 = rand.nextInt(20);

 

    public String toString() {

       return id + ":" + "i4:" + i4 + ", i5=" + i5;

    }

 

    public static void main(String[] args) {

       FinalData fd1 = new FinalData("fd1");

       System.out.println(fd1);

       System.out.println("Creating new FinalData");

       FinalData fd2 = new FinalData("fd2");

       System.out.println(fd1);

       System.out.println(fd2);

    }

}

 

结果

fd1:i4:6, i5=3

Creating new FinalData

fd1:i4:6, i5=3

fd2:i4:17, i5=3
示例部分展示了将final 数值定义为statici5 和非statici4 的区别。此区别只有在数值在运行期内被初始化时才会显现,这是因为编译器对编译期数值一视同仁。(并且它们可能因优化而消失。)当你运行程序时,就会看到这个区别。请注意,在fd1 fd2 中, i5 的值是不可以通过创建第二个FinalData 对象而加以改变的。这是因为它是 static,在装载时已被初始化,而不是每次创建新对象时都初始化。
示例4

class Value {

    int i;

 

    public Value(int i) {

       this.i = i;

    }

}

 

public class … {

    private Value v1=new Value(11);

    private final Value v2=new Value(22);

    private static final Value v3=new Value(33);

  

}

 

public static void main(String[] args) {

   

    fd1.v2.i++;// OK--Object isn't constant!

    fd1.v1=new Value(9);//OK--not final

    fd1.v2=new Value(0);//Error:Can't change reference

    fd1.v3=new Value(1);//Error:Can't change reference

   

}

v1 v3 的变量说明了final 引用的意义。正如你在main( )中所看到的,不能因为v2 final 的,就认为你无法改变它的值。由于它是一个引用,final 意味着你无法将v2 再次指向另一个新的对象。
示例5

public class … {

    private final int[] a={1,2,3,4,5,6};

   

}

 

public static void main(String[] args) {

   

    for(int i=0;i<fd1.a.length;i++)

 fd1.a[i]++;// OK--Object isn't constant!

    fd1.a=new int[3];//Error:Can't change reference   

}

对数组具有同样的意义(可以改变它的值,但不能指向一个新的对象),数组是另一种引用。

 

1.4解决final数组的局限性

尽管数组引用能被声明成 final,但是该数组的元素却不能。这意味着暴露 public final 数组字段的或者通过它们的方法将引用返回给这些字段的类都不是不可改变的。
// Not immutable -- the states array could be modified by a malicious

// callerpublic

class DangerousStates {

    private final String[] states = new String[] { "Alabama", "Alaska", "ect" };

 

    public String[] getStates() {

       return states;

    }

}

 

同样,尽管对象引用可以被声明成 final 字段,而它所引用的对象仍可能是可变的。如果想要使用 final 字段创建不变的对象,必须防止对数组或可变对象的引用“逃离”你的类。要不用重复克隆该数组做到这一点,一个简单的方法是将数组转变成 List
// Immutable -- returns an unmodifiable List insteadpublic

class SafeStates {

    private final String[] states = new String[] { "Alabama", "Alaska", "ect" };

 

    private final List statesAsList = new AbstractList() {

       public Object get(int n) {

           return states[n];

       }

 

       public int size() {

           return states.length;

       }

    };

 

    public List getStates() {

       return statesAsList;

    }

}

 

1.5关于final参数使用

还有一种用法是定义方法中的参数为final,对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用final进行声明,会防止你无意的修改而影响到调用方法。

 

1.6关于内部类中的参数变量

另外方法中的内部类在用到方法中的参变量时,此参数变量必须声明为final才可使用。
示例6 INClass.java

public class INClass {

    void innerClass(final String str) {

       class IClass {

           IClass() {

              System.out.println(str);

           }

       }

       IClass ic = new IClass();

    }

 

    public static void main(String[] args) {

       INClass inc = new INClass();

       inc.innerClass("Hello");

    }

}

2final方法

2.1final方法用途

1)为了确保某个函数的行为在继承过程中保持不变,并且不能被覆盖(overridding),可以使用final方法。

 

2class中所有的privatestatic方法自然就是final

 

2.2 finalprivate关键字

类中所有的private方法都隐式地指定是final的。由于无法取用private方法,所以也就无法覆盖它。
“覆盖”只有在某方法是基类的接口的一部分时才会出现。即,必须能将一个对象向上转型为它的基本类型并调用相同的方法。如果某方法为private,它就不是基类的接口的一部分。它仅是一些隐藏于类中的代码,只不过是具有相同的名称而已。但如果在导出类以相同的方法生成一个publicprotected或包访问权限方法的话,该方法就不会产生在基类中出现的“仅具有相同名称”的情况。此时,你并没有覆盖该方法,仅是生成了一个新的方法。由于private方法无法触及而且能有效隐藏,所以除了把它看成是因为它所归属的类的组织结构的原因而存在外,其他任何事物都不需要考虑它。

3final

将某个类的整体定义为final 时,该类无法被继承。而且由于final类禁止继承,所以final类中所有的方法都隐式指定为final的,因为无法覆盖它们。
final 用于类或方法是为了防止方法间的链接被破坏。例如,假定类 X 的某个方法的实现假设了方法 M 将以某种方式工作。将 X M 声明成 final 将防止派生类以这种方式重新定义 M,从而导致 X 的工作不正常。尽管不用这些内部相关性来实现 X 可能会更好,但这不总是可行的,而且使用 final 可以防止今后这类不兼容的更改。

4.参考资料

[1]Thinking in Java 3rd
[2] 关于javafinal方法,类,成员变量的讨论
[url]http://www.cublog.cn/u/11794/showart.php?id=117818[/url]
[3] java中的final
[url]http://blog.csdn.net/getmc/archive/[/url]2006/02/20/603878.aspx

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Android开发者快速上手Kotlin(九) 之 Kotlin与Java混合开发
    接《Android开发者快速上手Kotlin(八) 之 协程官方框架Channel、Select和Flow》文章继续。 16 Kotlin与Java混合开发 我们在前面介绍语法文章里或多或少有提到过可以使用一些如@JvmXX的注解来解决默认参数、静态成员等Kotlin和Java的兼容问题以及属性、空指针安全、反射等语法的区别和使用。今天我们就来进行一个全面的总结关于Kotlin和Java共存混合开发的各种情况。 16.1 属性读写 其实Java中并没有属性的概念,它并不是语法的规则,只是通过Getter和Setter约定来实现属性的逻辑。而在Kotlin是存在真正意义上的属性,所以在Kotlin里会自动识别Java的Getter和Setter。 同样道理,将Kotlin转成Java后会自动生成Getter和Setter。 更多Kotlin属性介绍 16.2 空类型安全 Kotlin中不区分装箱类型和基本类型,而且Kotlin中任意类型都有可空和不可空两种情况(默认不可空),若需要为空的情况,需要在类型后面加一个问号”?”。所以如果在Kotlin里想操作Java的代码时就会遇到一个平台类型,如果Java中返回的类型是String,那么IDE就会提示其类型是String!(带感叹号的类型实质上是不存在的,仅为IDE提示),当然我们在Android平台上开发的话,返回String
  • Java关键字介绍之this与super
    总结关键字this与super用法。 author: ZJ 07-3-12 Blog: [url]http://zhangjunhd.blog.51cto.com/[/url] 1.什么是super?什么是this? super关键字表示超(父)类的意思。this变量代表对象本身。 2.使用super&this调用成员变量和方法 可以使用super访问父类被子类隐藏的变量或覆盖的方法。当前类如果是从超类继承而来的,当调用super.XX()就是调用基类版本的XX()方法。见示例1。 当类中有两个同名变量,一个属于类(类的成员变量),而另一个属于某个特定的方法(方法中的局部变量),使用this区分成员变量和局部变量。见示例2。 示例1 class Person { protected void print() { System.out.println("The print() in class Person."); } } public class DemoSuper extends Person { public void print() { System.out.println("The print() in class DemoSuper."); super.print();// 调用父类的方法 } public static void main(String[] args)
  • javaSE基础内容大纲
    java基础语法: 1. Java语言的发展史 2. JDK的下载和安装 3. DOS命令的介绍和使用 4. Path环境变量的配置 5. 第一个代码HelloWorld案例 6. NotePad++软件的安装和使用 7. Java中的数据类型 8. 常量的使用 9. 变量的定义与使用 10. Java中代码的书写规范 11. 数据类型之间的转换 12. Java中的各种运算符操作 13. if分支语句的灵活使用 14. switch分支语句 15. for循环结构 16. while循环结构 17. do..while循环结构 18. 各种循环语句的区别和应用场景 19. 循环跳转控制语句 20. 嵌套循环的应用 21. 使用循环嵌套打印直角三角形 22. IDEA开发软件 23. 数组的动态初始化 24. 数组的访问格式 25. 数组的静态初始化 26. Java的内存划分和作用 27. 分析数组在内存中的存储 28. 方法的定义和调用 29. 方法的参数和返回值问题 30. 方法的重载(Overload) 31. 参数是基本类型和引用类型的区别 32. Debug断点调试的使用 面向对象基础: 1. 类和对象的概述 2. 分析对象在内存中的存储 3. 成员变量和局部变量的区别 4.private关键字的应用 5. this关键字的应用 6. this关键字的内存原理 7
  • Java全套课程修炼之Java小白入门篇
    温馨提示: 1、本文并非Java的唯一学习路线,程序羊仅仅是怀着分享的动力来汇总,仅供参考。如有争议,请及时联系程序羊。 2、看完此文之后,能不能全都学会,程序羊不敢保证,但是,唯一可以知道的一点就是,您至少应该知道按什么学习路线去学习Java了,并且可以学到一些,或许你还没有了解到的知识。 3、如果您觉得本文对您有用,可以收藏好,并给程序羊点个赞,以示鼓励,喜欢的朋友也可以点个关注喔,程序羊会不定时给您更新更多的干货。 阶段1 Java语言基础 1-1-Java基础语法 第1节 java运行环境 1_1_1_01_Java语言发展史 1_1_1_02_计算机进制转换 1_1_1_03_计算机存储单元 1_1_1_04_命令提示符_基本介绍 1_1_1_05_命令提示符_常用命令 1_1_1_06_Java语言的跨平台性 1_1_1_07_JDK、JRE与JVM 1_1_1_08_JDK的下载与安装 1_1_1_09_环境变量的配置 第2节 HelloWorld案例 1_1_2_10_HelloWorld程序的代码编 1_1_2_11_HelloWorld程序的编译 1_1_2_12_HelloWorld的常见问题 1_1_2_13_程序注释与HelloWorld 第3节 关键字&标识符 1_1_3_14_关键字的概念与特征 1_1_3_15_标识符的概念与规则 第4节 常量&变量
  • 阿里、字节跳动、京东、腾讯、小米高频面试题(Java岗)
    1.笔试常见的问题? 面试常见的问题上面给的面试题链接基本都有。我只提几点: 写SQL:写SQL很常考察group by、内连接和外连接。 手写代码:手写代码一般考单例、排序、线程、消费者生产者。我建议排序算法除了冒泡排序,最好还能手写一种其他的排序代码。试想:如果一般面试者都写的冒泡排序,而你写的是快速排序/堆排序,肯定能给面试官留下不错的印象。 2.面试流程? 让你自我介绍 问Java基础知识 问项目 情景问题,例如:你的一个功能上了生产环境后,服务器压力骤增,该怎么排查。 你有什么想问面试官的 3.面试常问的知识点? 1)集合相关问题(必问): HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。 HashMap和Hashtable的区别。 ArrayList、LinkedList、Vector的区别。 HashMap和ConcurrentHashMap的区别。 HashMap和LinkedHashMap的区别。 HashMap是线程安全的吗。 ConcurrentHashMap是怎么实现线程安全的。 2)多线程并发相关问题(必问): 创建线程的3种方式。 什么是线程安全。 Runnable接口和Callable接口的区别。 wait方法和sleep方法的区别。 synchronized、Lock
  • 深度复盘阿里、字节跳动、美团、腾讯、小米等名企高频面试专题,大厂面试真不难
    1.笔试常见的问题? 面试常见的问题上面给的面试题链接基本都有。我只提几点: 写SQL:写SQL很常考察group by、内连接和外连接。手写代码:手写代码一般考单例、排序、线程、消费者生产者。我建议排序算法除了冒泡排序,最好还能手写一种其他的排序代码。试想:如果一般面试者都写的冒泡排序,而你写的是快速排序/堆排序,肯定能给面试官留下不错的印象。 2.面试流程? 让你自我介绍问Java基础知识问项目情景问题,例如:你的一个功能上了生产环境后,服务器压力骤增,该怎么排查。你有什么想问面试官的 3.面试常问的知识点? 1)集合相关问题(必问): HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。HashMap和Hashtable的区别。ArrayList、LinkedList、Vector的区别。HashMap和ConcurrentHashMap的区别。HashMap和LinkedHashMap的区别。HashMap是线程安全的吗。ConcurrentHashMap是怎么实现线程安全的。 2)多线程并发相关问题(必问): 创建线程的3种方式。什么是线程安全。Runnable接口和Callable接口的区别。wait方法和sleep方法的区别。synchronized、Lock、ReentrantLock
  • 阿里,字节都不要我!卧薪尝胆33天,才艰难六面拿到美团offer,这也太难了吧,呜呜呜~
    1.笔试常见的问题? 面试常见的问题上面给的面试题链接基本都有。我只提几点: 写SQL:写SQL很常考察group by、内连接和外连接。手写代码:手写代码一般考单例、排序、线程、消费者生产者。我建议排序算法除了冒泡排序,最好还能手写一种其他的排序代码。试想:如果一般面试者都写的冒泡排序,而你写的是快速排序/堆排序,肯定能给面试官留下不错的印象。 2.面试流程? 让你自我介绍问Java基础知识问项目情景问题,例如:你的一个功能上了生产环境后,服务器压力骤增,该怎么排查。你有什么想问面试官的 3.面试常问的知识点? 1)集合相关问题(必问): HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList的底层实现。HashMap和Hashtable的区别。ArrayList、LinkedList、Vector的区别。HashMap和ConcurrentHashMap的区别。HashMap和LinkedHashMap的区别。HashMap是线程安全的吗。ConcurrentHashMap是怎么实现线程安全的。 2)多线程并发相关问题(必问): 创建线程的3种方式。什么是线程安全。Runnable接口和Callable接口的区别。wait方法和sleep方法的区别。synchronized、Lock、ReentrantLock
  • 提取bilibili网页视频目录,网页提取标签、属性,list到写入文本
    1、网页提取标签、及属性写入list # -*- coding:utf-8 -*- import requests from bs4 import BeautifulSoup html_doc3=""" <ul class="list-box"><li class="watched on"><a href="/video/BV1gp4y1q71w?p=1" class="" title="1.01 引言"><i class="van-icon-videodetails_play"></i><span class="s1">P1</span> 1.01 引言 </a></li><li class=""><a href="/video/BV1gp4y1q71w?p=2" class="" title="2.01 课前准备"><i class="van-icon-videodetails_play" style="display: none;"></i><span class="s1">P2</span> (内容太多写不下,忽略) 4.11.10 集群_选举策略 </a></li><li class=""><a href="/video/BV1gp4y1q71w?p=863" class="" title="4.11.11 集群_搭建集群"><i class="van-icon
  • 转载:Java学习路线(完整详细版)超详细
    Java学习路线 第一阶段:Java基础一.介绍二.Java开发介绍三.Java数组四.Java面向对象五.异常六.集合七.IO流八.多线程 第二阶段:JavaWeb一.介绍二.HTML5三.CSS3四.JavaScript五.MySQL或Oracle数据库的使用六.JDBC连接池七.Servlet八.JSP九.AJAX 第三阶段:Java框架一.介绍二.Spring三.Spring MVC四.MyBatis五.Svn和Git六.Maven七.项目实战演练 一门永不过时的编程语言——Java语言! Java编程语言占比: 据官方数据统计,在全球编程语言工程师的数量上,Java编程语言以1000万的程序员数量位居首位。 而且很多软件的开发都离不开Java编程,因此其程序员的数量最多。而在以Java编程为核心的开发领域中,javaEE程序员的需求量10年来一直居于首位! Java工程师就业: 通过各大招聘网站统计,全国海量公司都在招聘Java开发工程师北京Java开发工程师平均薪资,即16788元全国Java开发薪资前三:北京 上海 广州 本博客可作为: Java学习路线Java学习大纲 第一阶段:Java基础 一.介绍 Java基础课程内容涉及:Java开发介绍、Java数组、Java面向对象、常用基础类、集合、IO流、多线程、异常、反射。 二.Java开发介绍 第一部分
  • 打怪升级之小白的大数据之旅(十五)<Java基础语法之面向对象的匿名内部类>
    打怪升级之小白的大数据之旅(十五) Java基础语法之面向对象的内部类 上次回顾: 上一期,我们对面向对象的接口进行了介绍,接口在jdk8前可以理解为一个特殊一些的100%抽象类,是为了让java也可以实现的多继承的效果而存在.本期我将会带来面向对象最后一章内部类、匿名类,这一章中的匿名类是个重点,他为以后我们大数据相关的语法会有帮助,也是理解lambda表达式的基础。然后我会介绍一下java中的异常。好了,开始进入正题: 内部类 内部类就像名字一样,在一个类的内部定义的一个类,假设将一个类A定义在另一个类B里面,那么,里面的类A就成为内部类,B则称之为外部类 概述 为什么要声明内部类呢?请看下图: 准确的描述是这样的: 当一个事物的内部,还有一个部分需要一个完整的结构进行描述,而这个内部的完整结构又只为外部事物提供服务,不在其他地方单独使用,那么整个内部的完整结构最好使用内部类就像上图,人体可以理解为一个外部类,那么,各个器官就是由许多的内部类组成,每个内部类都会封装自己独特的属性和行为,这些内部类(器官)只为这个人服务,不在其他地方单独使用(器官移植就相当于还是为人这个类服务)因为内部类在外部类里面,因此可以直接访问外部类的私有成员内部类的分类 根据内部类声明的位置(如同变量的分类),我们可以将内部类分为: 成员内部类 静态内部类 费静态成员内部类局部内部类 有名字的局部内部类
  • java知识点总结,学习路线总结(非常详细)!
    学习地址:https://how2j.cnJava基础课程Java基础课程内容涉及:Java开发介绍、Java数组、Java面向对象、常用基础类、集合、IO流、多线程、异常、反射。第一部分:Java开发介绍1. DOS常用命令2. JVM、JRE、JDK之间的关系3. Java开发环境的搭建:安装JDK,配置环境变量4. Java入门程序(Java的开发流程)5. Java的注释,标识符、标识符的命名规范6. Java基本数据类型7. 变量和常量的定义及初始化8. Java的运算符9. 运算符的优先级10. Java分支语句之if...else11. 循环的嵌套12. 方法的定义13. 方法的形参和实参14. 方法的递归调用第二部分:Java数组1. Java 数组的定义2. Java 数组的声明3. 数组的优势与局限4. 数组的遍历访问(普通循环,增强for循环)5. 数组元素的顺序查找6. 数组元素的冒泡法排序7. Arrays工具类的使用8. 二维数组 第三部分:Java面向对象1. 面向对象设计思想2. 面向对象的分析与设计3. Java与面向对象4. 类中成员变量的定义与意义5. 构造方法的定义和调用6. 面向对象的封装特性7. 局部变量和成员变量的作用域问题8. 静态属性、静态方法、静态代码块9. 面向对象的继承特性10. 继承中构造方法的细节11
  • Java内存模型和底层实现原理
    Java内存模型把Java虚拟机内部划分为线程栈和堆。这张图演示了Java内存模型的逻辑视图。 每一个运行在Java虚拟机里的线程都拥有自己的线程栈。这个线程栈包含了这个线程调用的方法当前执行点相关的信息。一个线程仅能访问自己的线程栈。 每当我们执行一个方法时,我们都会将该方法打包成一个栈帧,然后将其将栈帧放入我们的线程栈之内,这就是为什么我们在 并发安全(一)—— 如何保证线程安全 中提到说,栈封闭可以保证我们的线程安全。因为每一个线程仅能访问自己的线程栈。 另外我们执行方法都会像上述那种所说,打个栈帧,然后放入栈内存中,执行完后就会从栈内存中取出,这个压栈弹栈的过程,我们在 Spring的AOP底层源码后续——AOP的调用流程及总结图解 中就有深刻的体会。 所有原始类型(boolean、byte、short、char、int、long、float、double)的局部变量都直接保存在线程栈当中,对于它们的值各个线程之间都是独立的。对于原始类型的局部变量,一个线程可以传递一个副本给另一个线程,也就是值传递,当它们之间是无法共享的。 一个局部变量如果是原始类型,那么它会被完全存储到栈区。 一个局部变量也有可能是一个对象的引用,这种情况下,这个本地引用会被存储到栈中,但是对象本身仍然存储在堆区。 所以:存在栈内存中,肯定是独占的,存在堆内存中的对象,因为只有是局部变量
  • 面试宝典(二)之经典面试题(含详细答案)
    文章标题 问题一: 简单介绍下你自己问题二: String为什么是final的?问题三: String、StringBuff、StringBuilder的区别问题四: abstract、final、static关键字的区别?抽象类可以继承实体类?抽象类可以实例化?问题五: 声明和定义的区别问题六: HashMap和HashTable的区别问题七: 解决Hash冲突的方法问题八: final、finally、finalize的区别问题九: equals和==的区别问题十: 重写(override)和重载(overload)的区别十一总结    温馨提示: 本文大约3520字,阅读完大概需要3-5分钟,希望您能耐心看完,倘若你对该知识点已经比较熟悉,你可以直接通过目录跳转到你感兴趣的地方,希望阅读本文能够对您有所帮助,如果阅读过程中有什么好的建议、看法,欢迎在文章下方留言或者私信我,您的意见对我非常宝贵,再次感谢你阅读本文。 问题一: 简单介绍下你自己   解题思路: 要回答好这个问题,首先要了解面试官询问的意图,而不是上来就像记流水账一样回答,这样给面试官的印象分就减少了。   面试官询问这个问题,主要的意图大概有: 观察你是否有为面试提前做准备,如果有提前准备,回答的时候就不会磕磕巴巴的。观察你的语言表达能力,如果你的回答东一点、西一点,印象分会减少。为后面的面试问题做铺垫
  • Java 数据持久化系列之 HikariCP (一)
    在上一篇《Java 数据持久化系列之池化技术》中,我们了解了池化技术,并使用 Apache-common-Pool2 实现了一个简单连接池,实验对比了它和 HikariCP、Druid 等数据库连接池的性能数据。在性能方面,HikariCP遥遥领先,而且它还是 Spring Boot 2.0 默认的数据库连接池。下面我们就来了解一下这款明星级开源数据库连接池的实现。本文的主要内容包括:HikariCP 简介,介绍它的特性和现况。HikariCP 的配置项详解,分析部分配置的影响。HikariCP 为什么这么快,介绍其优化点。这里啰嗦两句,由于本系列会涉及很多开源项目,比如说 HikariCP、Druid、Mybatis等,所以简单聊一下我对学习开源项目的认识,这也是我自己行文或者组织系列文章顺序的思路,后续有时间再详细总结一下。安装并检查提供的所有工具,比如 Redis 目录下的 redis-check-aof 等工具的作用,这些工具都是官方特意提供的,一般都是日常经常要使用的,了解其功能。运行,学习所有配置项的功能,原理和优缺点,比如 Redis 的内存溢出控制策略 maxmemory-policy 的可选值都有哪些,分别对应的策略是什么含义,适用于哪些场景等。原理研究,针对关键特性进行研究,比如 Netty 的异步 NIO 和零拷,HikariCP的高并发优缺点对比
  • 2021年最新Java的学习路线来了~
    一门永不过时的编程语言——Java 软件开发,5G时代,万物互联,更多的终端会使用安卓系统,随之而来的Java开发必然是会越来越火爆,所以学习Java是必要且必须的,下边就是总结了下Java的学习路线~ 【需要java资料的私信我免费领取】 Java编程语言占比: 据官方数据统计,在全球编程语言工程师的数量上,Java编程语言以1000万的程序员数量位居首位。 而且很多软件的开发都离不开Java编程,因此其程序员的数量最多。而在以Java编程为核心的开发领域中,javaEE程序员的需求量10年来一直居于首位! Java工程师就业: 1.通过各大招聘网站统计,全国海量公司都在招聘Java开发工程师 2.北京Java开发工程师平均薪资,即16788元 3.全国Java开发薪资前三:北京 上海 广州 工具/原料 Java学习路线Java学习大纲 Java基础课程 1 Java基础课程内容涉及:Java开发介绍、Java数组、Java面向对象、常用基础类、集合、IO流、多线程、异常、反射。 第一部分:Java开发介绍 DOS常用命令 JVM、JRE、JDK之间的关系 Java开发环境的搭建:安装JDK,配置环境变量 Java入门程序(Java的开发流程) Java的注释,标识符、标识符的命名规范 Java基本数据类型 变量和常量的定义及初始化 Java的运算符 运算符的优先级
  • 2020Java学习路线(珍藏版)
    一门永不过时的编程语言——Java 软件开发,虽然我是做C/C++开发的,但是也是学习过并且之后肯定还要继续学习Java的,原因就是5G时代,万物互联,更多的终端会使用安卓系统,随之而来的Java开发必然是会越来越火爆,所以学习Java是必要且必须的,下边就是总结了下Java的学习路线 Java编程语言占比: 据官方数据统计,在全球编程语言工程师的数量上,Java编程语言以1000万的程序员数量位居首位。 而且很多软件的开发都离不开Java编程,因此其程序员的数量最多。而在以Java编程为核心的开发领域中,javaEE程序员的需求量10年来一直居于首位! Java工程师就业: 1.通过各大招聘网站统计,全国海量公司都在招聘Java开发工程师 2.北京Java开发工程师平均薪资,即16788元 3.全国Java开发薪资前三:北京 上海 广州 工具/原料 Java学习路线Java学习大纲 Java基础课程 1 Java基础课程内容涉及:Java开发介绍、Java数组、Java面向对象、常用基础类、集合、IO流、多线程、异常、反射。 2 第一部分:Java开发介绍 DOS常用命令 JVM、JRE、JDK之间的关系 Java开发环境的搭建:安装JDK,配置环境变量 Java入门程序(Java的开发流程) Java的注释,标识符、标识符的命名规范 Java基本数据类型
  • 设计模式之单例模式
    基本介绍: 所谓类的单例设计模式,就是采取一定的方法保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。 实现方式: 1、饿汉式 class Singleton { // 构造器私有化,防止外部使用new关键字创建实例 private Singleton() {} // 内部创建对象实例 private static final Singleton SINGLETON = new Singleton(); // 提供一个公有的静态方法,返回实例对象 public static Singleton getSingleton(){ return SINGLETON; } } 优缺点: 在类加载阶段就完成实例化,避免了线程同步问题。没有达到懒加载(Lazy Loading)的效果,可能造成内存浪费。 2、懒汉式 class Singleton { // 构造器私有化,防止外部使用new关键字创建实例 private Singleton() {} private static Singleton singleton; // 提供一个公有的静态方法,当使用到该方法时,才创建实例对象 public static Singleton getSingleton(){ if (singleton == null) { singleton = new
  • android自学流程!Android性能优化之启动优化实战篇!附带学习经验
    目录 想要成为一名优秀的Android开发,你需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样。 PagerAdapter 介绍ViwePager 缓存策略ViewPager 布局处理ViewPager 事件处理相关内容 Java相关 容器(HashMap、HashSet、LinkedList、ArrayList、数组等) 内存模型 垃圾回收算法(JVM) 4、垃圾回收机制和调用 System.gc()的区别? 类加载过程(需要多看看,重在理解,对于热修复和插件化比较重要) 反射 多线程和线程池 设计模式(六大基本原则、项目中常用的设计模式、手写单例等) Java 四大引用 Java 的泛型 final、finally、finalize 的区别 接口、抽象类的区别 Android 相关 自定义 View 事件拦截分发 解决过的一些性能问题,在项目中的实际运用 性能优化工具 性能优化 (讲讲你自己项目中做过的性能优化) Http[s]请求慢的解决办法(DNS、携带数据、直接访问 IP) 缓存自己如何实现(LRUCache 原理) 图形图像相关:OpenGL ES 管线流程、EGL 的认识、Shader 相关 SurfaceView、TextureView、GLSurfaceView 区别及使用场景 动画、差值器、估值器(Android中的View动画和属性动画 - 简¹
  • 代码理解java多线程 (三) - JDK工具篇(3)- 锁接口和类
    目录 第十四章 锁接口和类 14.1 synchronized的不足之处 14.2 锁的几种分类 14.2.1 可重入锁和非可重入锁 14.2.2 公平锁与非公平锁 14.2.3 读写锁和排它锁 14.3 JDK中有关锁的一些接口和类 14.3.1 抽象类AQS/AQLS/AOS 14.3.2 接口Condition/Lock/ReadWriteLock 14.3.3 ReentrantLock 14.3.4 ReentrantReadWriteLock 14.3.5 StampedLock 第十四章 锁接口和类 前面我们介绍了Java原生的锁——基于对象的锁,它一般是配合synchronized关键字来使用的。实际上,Java在java.util.concurrent.locks包下,还为我们提供了几个关于锁的类和接口。它们有更强大的功能或更高的性能。 14.1 synchronized的不足之处 我们先来看看synchronized有什么不足之处。 如果临界区是只读操作,其实可以多线程一起执行,但使用synchronized的话,同一时间只能有一个线程执行。synchronized无法知道线程有没有成功获取到锁使用synchronized,如果临界区因为IO或者sleep方法等原因阻塞了,而当前线程又没有释放锁,就会导致所有线程等待。 而这些都是locks包下的锁可以解决的。
  • Android性能优化之APK优化,挥泪整理面经
    目录 想要成为一名优秀的Android开发,你需要一份完备的知识体系,在这里,让我们一起成长为自己所想的那样。 PagerAdapter 介绍ViwePager 缓存策略ViewPager 布局处理ViewPager 事件处理相关内容 1、Java se基础 1).Java基本数据类型与表达式,分支循环。 2).String和StringBuffer的使用、正则表达式。 3).面向对象的抽象,封装,继承,多态,类与对象,对象初始化和回收;构造函数、this关键字、方法和方法的参数传递过程、static关键字、内部类。 4).对象实例化过程、方法的覆盖、final关键字、抽象类、接口、继承的优点和缺点剖析;对象的多态性:子类和父类之间的转换、抽象类和接口在多态中的应用、多态带来的好处。 5).Java异常处理,异常的机制原理。 6).常用的设计模式:Singleton、Template、Strategy模式。 7).JavaAPI介绍:种基本数据类型包装类,System和Runtime类,Date和DateFomat类等。 8).Java集合介绍:Collection、Set、List、ArrayList、LinkedList、Hashset、Map、HashMap、Iterator等常用集合类API。 9).JavaI/O输入输出流:File和FileRandomAccess类