精华内容
下载资源
问答
  • final 方法

    千次阅读 2012-08-14 17:01:36
    使用final方法的第二个原因是效率。如果你将一个方法指明为final,就是同意编译器将针对 该方法的所有调用都转为内嵌(inline)调用。当编译器发现一个final方法调用命令时,它 会根据自己的谨慎判断,跳过插入

    使用 final 方法的原因有两个。第一个原因是把方法锁定,以预防任何继承类修改它的意义。
    这是出于设计的考虑:你想要确保在继承中方法行为保持不变,并且不会被重载。
     
    使用final方法的第二个原因是效率。如果你将一个方法指明为final,就是同意编译器将针对
    该方法的所有调用都转为内嵌(inline)调用。当编译器发现一个final方法调用命令时,它
    会根据自己的谨慎判断,跳过插入程序代码的正常方式而执行方法调用机制(将参数压入栈,
    跳至方法代码处并执行,然后跳回并清除栈中的参数,处理返回值。),并且以方法体中的实
    际代码的复本来替代方法调用。这将消除方法调用的开销。当然,如果一个方法很大,你的
    程序代码就会膨胀,你可能看不到内嵌带来的任何性能提高,因此,你所取得的性能提高会
    因为花费于方法内的时间总量而被缩减。这意味着Java编译器能够观察到这些情况并明智地
    抉择是否对final方法执行内嵌动作。然而,最好是让编译器和JVM仅在你明确表示要阻止重
    载时,再处理效率事项,并将方法指明为final 。

     

    类中所有的 private 方法都被隐含是 final 的。由于你无法取用 private 方法,所以你也无法
    重载之。你可以对 private 方法增加 final  修饰符,但这并不能给该方法增加任何额外的意
    义。
     
    这一问题会造成混淆。因为如果你试图重载一个 private 方法(隐含是 final 的),看起来是
    奏效的,而且编译器也不会给出错误信息

     

    “重载”只有在某方法是基类的接口的一部分时才会出现。即,你必须能将一个对象向上转
    型为它的基本类型并调用相同的方法(这一点在下一章将得以阐明)。如果某方法为 private,
    它就不是基类的接口的一部分。它仅是一些隐藏于类中的程序代码,不过具有相同的名称而
    已。但你如果在导出类中以相同的名称生成一个 public、protected 或包访问权限(package
    access)方法的话,该方法就不会产生在基类中出现的“仅具有相同名称”的情况。此时你
    并没有重载方法,你仅是生成了一个新的方法。由于 private 方法无法触及又不能有效隐藏,
    所以仅仅是因为考虑到定义它的类的程序代码组织,它们才有存在的意义,除此之外,其他
    任何事物都不需要把它纳入考虑的范畴。

    展开全文
  • Java中的final变量、final方法和final类

    万次阅读 多人点赞 2018-12-13 17:39:24
    1、final变量 final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。例如,在类中定义PI值,可以使用如下语句: final double PI=3.14; 在Java中定义全局...

    1、final变量

    final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。例如,在类中定义PI值,可以使用如下语句:

    final double PI=3.14;

    在Java中定义全局常量,通常使用public static final修饰,这样的常量只能在定义是被赋值。

    public static final double PI_VAULE = 3.14;

    规范:被定义为final的常量定义时需要使用大写字母命名,并且中间使用下划线进行连接。

    常量示例:

    import java.util.Random;
    
    class Test
    {
    	int i = 0;
    }
    
    /**
     * 常量示例
     * 
     * @author pan_junbiao
     *
     */
    public class FinalData
    {
    	static Random rand = new Random();
    	private final int VALUE_1 = 9; // 声明一个final常量
    	private static final int VALUE_2 = 10; // 声明一个final、static常量
    	private final Test test = new Test(); // 声明一个final引用
    	private Test test2 = new Test(); // 声明一个不是final的引用
    	private final int[] a = { 1, 2, 3, 4, 5, 6 }; // 声明一个定义为final的数组
    	private final int i4 = rand.nextInt(20);
    	private static final int i5 = rand.nextInt(20);
    
    	public String toString()
    	{
    		return "i4值:" + i4 + " i5值:" + i5 + " ";
    	}
    
    	public static void main(String[] args)
    	{
    		FinalData data = new FinalData();
    
    		// 报错:不能改变定义为final的常量值
    		// data.VALUE_1 = 8;
    
    		// 报错:不能改变定义为final的常量值
    		// data.VALUE_2 = 9;
    
    		// 报错:不能将定义为final的引用指向其他引用
    		// data.test = new Test();
    
    		// 正确: 可以对指定为final的引用中的成员变量赋值
    		data.test.i = 1;
    
    		// 正确: 可以将没有定义为final的引用指向其他引用
    		data.test2 = new Test();
    
    		// 报错:不能对定义为final的数组赋值
    		// int b[] = { 7, 8, 9 };
    		// data.a = b;
    
    		// 但是final的数组中的每一项内容是可以改变的
    		for (int i = 0; i < data.a.length; i++)
    		{
    			data.a[i] = 9;
    		}
    
    		System.out.println(data);
    		System.out.println("data2");
    		System.out.println(new FinalData());
    	}
    }

    执行结果:

     

    从上述执行结果中可以发现i5的值是相同的。

    全局常量:

    我们知道一个被定义为final的对象引用只能指向唯一一个对象,不可以将它再指向其它对象,但是一个对象的值却是可以改变的,那么为了使一个常量真正做到不可更改,可以将常量声明为static final。

    示例:在项目中创建FinalStaticData类,在该类中创建Random类的对象,在主方法中分别输出类中定义的final变量a1与a2。

    import static java.lang.System.out;
    
    import java.util.Random;
    
    /**
     * FinalStaticData类
     * 
     * @author pan_junbiao
     *
     */
    public class FinalStaticData
    {
    	private static Random rand = new Random(); // 实例化一个Random类对象
    	// 随机产生0~10之间的随机数赋予定义为final的a1
    	private final int a1 = rand.nextInt(10);
    	// 随机产生0~10之间的随机数赋予定义为static final的a2
    	private static final int a2 = rand.nextInt(10);
    
    	public static void main(String[] args)
    	{
    		FinalStaticData fdata = new FinalStaticData(); // 实例化一个对象
    		// 调用定义为final的a1
    		out.println("重新实例化对象调用a1的值:" + fdata.a1);
    		// 调用定义为static final的a2
    		out.println("重新实例化对象调用a2的值:" + fdata.a2);
    		// 实例化另外一个对象
    		FinalStaticData fdata2 = new FinalStaticData();
    		out.println("重新实例化对象调用a1的值:" + fdata2.a1);
    		out.println("重新实例化对象调用a2的值:" + fdata2.a2);
    	}
    }

    运行结果:

     

    从本示例运行结果中可以看出,定义为final的常量不是恒定不变的,将随机数赋予定义为final的常量,可以做到每次运行程序时改变a1的值。但是a2与a1不同,由于它被声明为static final形式,所以在内存中为a2开辟了一个恒定不变的区域,当再次实例化一个FinalStaticData对象时,仍然指向a2这块内存区域,所以a2的值保存不变。a2是在装载时被初始化,而不是每次创建新对象时被初始化;而a1会重新实例化对象时被更改。

    最后总结一下在程序中final数据可以出现的位置,如下程序。

    /**
     * 总结一下在程序中final数据可以出现的位置
     * 
     * @author pan_junbiao
     *
     */
    public class FinalDataTest
    {
    	// final成员变量不可更改
    	final int VALUE_ONE = 6;
    
    	// 在声明final成员变量时没有赋值,称为空白final
    	final int BLANK_FINALVAULE;
    
    	// 在构造方法中为空白final赋值
    	public FinalDataTest()
    	{
    		BLANK_FINALVAULE = 8;
    	}
    
    	// 设置final参数,不可以改变参数x的值
    	int doIt(final int x)
    	{
    		return x + 1;
    	}
    
    	// 局部变量定义为final,不可以改变i的值
    	void doSomething()
    	{
    		final int i = 7;
    	}
    }

     

    2、final方法

    首先,我们应该了解定义为final的方法不能被重写

    将方法定义为final类型可以防止任何子类修改该类的定义与实现方式,同时定义为final的方法执行效率要高于非final方法。在修饰权限中曾经提到过private修饰符,如果一个父类的某个方法被设置为private修饰符,子类将无法访问该方法,自然无法覆盖该方法,所以一个定义为private的方法隐式被指定为final类型,这样无须将一个定义为private的方法再定义为final类型。

    语法:

    private final void test()
    {
    }

     

    3、final类

    定义为final的类不能被继承。

    如果希望一个类不允许任何类继承,并且不允许其他人对这个类有任何改动,可以将这个类设置为final形式。

    final类的语法如下:

    final 类名{}

    如果将某个类设置为final形式,则类中的所有方法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或非final形式。

    示例:在项目中创建FinalClass类,在类中定义doit()方法和变量a,实现在主方法中操作变量a自增。

    /**
     * 定义final类
     * 
     * @author pan_junbiao
     *
     */
    final class FinalClass
    {
    	int a = 3;
    
    	void doit()
    	{
    	}
    
    	public static void main(String args[])
    	{
    		FinalClass f = new FinalClass();
    		f.a++;
    		System.out.println(f.a); // 结果:4
    	}
    }

     

    4、总结

    下面总结了一些使用final关键字的好处:

    (1)final关键字提高了性能。JVM和Java应用都会缓存final变量。

    (2)final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。

    (3)使用final关键字,JVM会对方法、变量及类进行优化。

    不可变类:

    创建不可变类要使用final关键字。不可变类是指它的对象一旦被创建了就不能被更改了。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不用额外的同步开销等等。

    关于final的重要知识点:

    (1)final关键字可以用于成员变量、本地变量、方法以及类。

    (2)final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。

    (3) 你不能够对final变量再次赋值。

    (4)本地变量必须在声明时赋值。

    (5)在匿名类中所有变量都必须是final变量。

    (6)final方法不能被重写。

    (7)final类不能被继承。

    (8)final关键字不同于finally关键字,后者用于异常处理。

    (9)final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。

    (10)接口中声明的所有变量本身是final的。

    (11)final和abstract这两个关键字是反相关的,final类就不可能是abstract的。

    (12)final方法在编译阶段绑定,称为静态绑定(static binding)。

    (13)没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。

    (14)将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。

    (15)按照Java代码惯例,final变量就是常量,而且通常常量名要大写。
     

    展开全文
  • spring aop final 方法

    千次阅读 2019-07-17 11:15:31
    最近做项目用到了spring aop,由于在项目里面用到了模板方法模式,在抽象类里面有一个final 方法。controller 调用这个final 方法的时候报空指针异常,一般我们都知道使用 aop 在controller 中注入的对象是spring ...

    最近做项目用到了spring aop,由于在项目里面用到了模板方法模式,在抽象类里面有一个final 方法。controller 调用这个final 方法的时候报空指针异常,一般我们都知道使用 aop 在controller 中注入的对象是spring 创建的代理对象,默认使用cglib。这里我们称代理对象为 proxy,称被代理的对象是target。在debuge的过程中发现,spring 注入到controller的proxy 中的所有属性都是null,包括日志logger都是null,即使 我写了 private String kk=“1111”,这个 kk 属性在proxy 中也是null。在本次中由于调用了proxy中的方法所以报了空指针异常。可是我在用aop定义切面的时候用的是 @annotation 定义的,按道理说只会拦截某一个方法,其他的方法应该直接调用 target 中相应的方法,主要是这个方法是 final 修饰的。由于默认使用cglib 来生成proxy,这个proxy就是 target的子类。而对于 final 方法子类是不能覆盖的,走的代码流程依然是 target 里面的。这是最坑的一个地方,我在网上找了很多资料,绝大多数都是说,对于没有final 修饰的方法是直接调用proxy的发方法,对于有 final 修饰的方法是调用target方法。按照这种想法proxy和target只是一个实例。类的结构类似这种
    在这里插入图片描述
    Demo 是 target DemoSub 是 proxy。我们只有一个实例就是 DemoSub。在调用DemoSub ,由于 kkk 方法用final 修饰了,DemoSub 不能覆盖。所以当调用kkk方法的时候实际是调用Demo的代码。***我觉得这是不正确的。***。主要是实例个数的问题。如下
    在这里插入图片描述
    最终生成的是两个实例,在proxy中有一个属性关联target。我们注入的proxy对象,如果是final 方法,直接就走 proxy的kkk方法,这个时候proxy中所有的属性是没有赋值都是null,其中proxy中也有一个隐式指针super执行其父类,但这个父类也是没有被spring 容器处理过的。比如里面的autowrite 属性都是null,如果不是final 修饰的方法,proxy中会先查看当前方法是否被定义为拦截的,如果是要拦截的则需要先执行 @Before 或者 @Around 注释的方法。如果不是则用 proxy中关联的 target 直接invoke 处理,这个target 才是我们真正的对象,里面所有的属性都是都是被处理过的。所有的aware接口也是被调用过的。
    总结一下主要是生成了几个对象,按照网上说的之生成了一个对象,用supper调用,可实际上有两个,proxy中有个属性和target做关联了。
    后面还有一个问题。切面逻辑无法被执行到。还是上面的例子去掉final
    在这里插入图片描述
    在这里我拦截的方法是syahi而我controller中调用的是 kkk 方法。这个时候对syahi方法的拦截逻辑是无法被执行的。主要是在controller中注入的是proxy 调用proxy的kkk方法,proxy发现这个方法没有被拦截,所以直接用 target 执行,这个时候执行kkk方法的对象变成了target,这里的this 指向是 target对象。在kkk方法里面调用 syahi 方法也就只是调用 target 的syahi 方法,想要拦截逻辑被执行这里调用syahi方法的对象不能是 target 必须是 proxy。spring aop中可以处理源码如下
    在这里插入图片描述
    有一个AopContext,应该通过 ThreadLocal 。在kkk方法改动如下

        public void kkk(){
            ((Demo) AopContext.currentProxy()).syahi();
            System.out.println("kkkk");
        }
    
    

    即可。在这里记录一下。

    展开全文
  • final类与final方法

    千次阅读 2016-03-07 16:31:39
    final方法---不可被覆盖。  final类不能被继承。  如果我们不希望一个类被继承,我们使用final来修饰这个类。这个类将无法被继承。比如我们设定的Math类,涉及了我们要做的数学计算方法,这些算法也没有必要修改...
    final---用于类、方法前。 
    
    final类---不可被继承。 
    final方法---不可被覆盖。 
    final类不能被继承。 
    如果我们不希望一个类被继承,我们使用final来修饰这个类。这个类将无法被继承。比如我们设定的Math类,涉及了我们要做的数学计算方法,这些算法也没有必要修改,也没有必要被继承,我们把它设置成final类型。

    复制代码代码如下:

    <? 
    //声明一个final类Math 
    final class Math{ 
    public static $pi = 3.14; 

    public function __toString(){ 
    return "这是Math类。"; 


    $math = new Math(); 
    echo $math; 

    //声明类SuperMath 继承自 Math类 
    class SuperMath extends Math { 

    //执行会出错,final类不能被继承。 

    ?> 

    程序运行结果  

    复制代码代码如下:
    Fatal error: Class SuperMath may not inherit from final class (Math) in E:\PHPProjects\test.php on line 14


    final方法不能被重写 
    如果不希望类中的某个方法被子类重写,我们可以设置这个方法为final方法,只需要在这个方法前加上final修饰符。 

    如果这个方法被子类重写,将会出现错误。 
    复制代码代码如下:

    <? 
    //声明一个final类Math 
    class Math{ 
    public static $pi = 3.14; 
    public function __toString(){ 
    return "这是Math类。"; 

    public final function max($a,$b){ 
    return $a > $b ? $a : $b ; 


    //声明类SuperMath 继承自 Math类 
    class SuperMath extends Math { 
    public final function max($a,$b){} 

    //执行会出错,final方法不能被重写。 

    ?> 


    程序运行结果 

    复制代码代码如下:
    Fatal error: Class SuperMath may not inherit from final class (Math) in E:\PHPProjects\test.php on line 16
    展开全文
  • final方法和private方法的区别

    千次阅读 2018-12-23 16:55:19
    final方法和private方法的区别 private,protected,public和internal的区别 static private 与 final 的用法总结   1、private表示私有的,只在本类内可见。 private的属性或方法对子类来说不能够继承。 2、...
  • Java中的final类和final方法

    千次阅读 2018-07-20 20:44:20
    final类不允许被继承。 final方法不能被子类重写。
  • final方法:表示方法不可被子类重写(覆盖) final变量:初始化一次后值不可变 final类:类不能被继承,内部的方法和变量都变成final类型 final对象:指对象的引用不可变,但是对象的值可变,即指向的是同一个...
  • final方法的使用

    千次阅读 2018-11-22 10:09:22
    1.final方法的使用原因有两个,1.把方法锁定,以防止任何继承类来修改它的含义,确保在继承中方法行为保持不变,并且不会被覆盖。 final和private关键字: 类中所有的private关键字都是隐式地指定为final,由于...
  • final方法和final类,内部类

    千次阅读 2015-08-13 21:07:12
    1.变量可以声明为final,说明该变量是...因为子类不可能重载private方法,所以声明为private的方法隐式地为final方法。声明为static方法也隐式为final方法,因为只能重载非静态方法。声明为final的类不能为超类。fina
  • java final方法与java内联函数

    千次阅读 2018-06-07 13:44:32
    《java编程思想》中讲到final方法时提到,使用final方法原因有两个, 一、锁定方法。防止任何继承类修改、覆盖 二、效率。在java早期实现中,如果将一个方法指明为final,就是同意编译器将针对该方法的调用都转化...
  • 终止继承:Final类和Final方法

    千次阅读 2016-05-18 17:23:21
    答:只有当需要确保类中的所有方法都不被重写时才应该建议最终类(Final),Final关键字将为这些方法提供安全,没有任何人能够重写Final类中的方法,因为不能继承。 下面用代码说明下Final
  • (易混点)java中,关于子类继承父类的private方法与final方法 对于子类继承父类的方法,相信很多人都已经掌握得非常熟悉了,今天由于在做牛客网的一道关于这个知识点的面试题,忽略了一个非常重要的细节,导致入坑...
  • Java的抽象类中可以定义final方法吗?不太清楚,请指教谢谢
  • java中final方法

    万次阅读 2017-03-16 17:53:02
    final修饰的变量为常量 final修饰的方法不能被重写,不能被覆盖 final修饰的类不能被继承
  • final方法不能被覆盖,可被重载(方法名相同而参数不同) Given: class Pizza { java.util.ArrayList toppings; public final void addTopping(String topping) {  // 这里不能用final,无法覆盖,应...
  • spring aop final方法

    千次阅读 2017-12-27 14:57:27
    Spring AOP默认使用cglib,会生成目标对象...但是当目标类中某个方法带有final关键字时,这个方法不能被重写,因此代理对象中没有这个方法,因此会调用目标对象的方法。 比如以下代码: @Service public class Car{
  • 【0】README0.1)本文描述+源代码均 转... final 域被设置后, 不能再对它进行更改, 即没有 setter 更改器方法; 1.2)不可变的类:如果类中的每个方法都不会改变其对象,这种类就是不可变的类; 1.3)对于可变的类
  • 子类是否可以重写父类的final方法,答案是:不可以! 父类Person: 子类SubPerson: Question 2: 子类是否可以重载父类的final方法,答案是可以的! 父类Add  子类 SubAdd: ...
  • 为什么得需要使用final修饰符继承关系最大的弊端是破坏封装:子类能访问父类的实现细节,而且可以通过方法覆盖的形式修改实现细节。final本身的含义是“最终的,不可改变的”,它可以修饰抽象类,非抽象方法和变量。...
  • final方法---不可被覆盖。final类不能被继承。如果我们不希望一个类被继承,我们使用final来修饰这个类。于是这个类将无法被继承。 比如我们设定的Math类,涉及了我们要做的数学计算方法,这些算法也没有必要修改,...
  • http://blog.sina.com.cn/s/blog_4d4b74b301000afn.html 1.定义及编程技巧 ...* final方法是在派生类中不能被覆盖的方法,final类是不能被覆盖的类。一个类可以含有final方法 * final类和f
  • 譬如,final 类, final 方法, 私有方法, 静态方法, 构造函数都是无法通过子类型进行重写的。所以除非特别需要,在 Mockito 无法胜任时都求助于 JMockit,JMockit 借助于 javaagent 取得了 JVM 的高控制权才得已...
  • 50 Java final 常量池 final方法

    千次阅读 2014-02-09 07:27:38
    * 例如:Object类里就有个final方法:getClass(), */ //下面程序师徒重写final方法,将会引发编译错误 public class FinalMethod { //用final修饰的方法 public final void test(){}; } class Sub extends ...
  • 昨天在一个群里面一个群友问道final 方法可不可以重载,我不假思索的说final 方法不能继承不能重载。后来晚上睡不着觉想想总觉得不对头,翻翻书一看自己简直就是胡说八道,才意识到这些基础概念的东西时间久了不深究...
  • java final方法执行效率测试

    千次阅读 2010-05-03 12:22:00
    在使用final修饰方法的时候,编译器会将被final修饰过的方法插入到调用者代码处,提高运行速度和效率,但被final修饰的方法体不能过大,编译器可能会放弃内联,但究竟多大的方法会放弃,我还没有做测试来计算过。...
  • final方法在Spring AOP中的注意事项

    千次阅读 2014-06-05 18:58:20
    注意:Spring AOP默认使用cglib会生成目标对象的子类,然后调用set时会直接设置代理对象的data,所以造成了target的... 当你调用get方法时因为是final 所以没有被代理 直接调用的是目标对象的,所以是null。 

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,351,590
精华内容 540,636
关键字:

final方法