精华内容
下载资源
问答
  • Java的transient关键字

    2017-10-14 08:34:04
    一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化...

    Java中的transient关键字

    http://www.importnew.com/21517.html

    一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化。但是有种情况是有些属性是不需要序列号的,所以就用到这个关键字。只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    /**
     * @description 使用transient关键字不序列化某个变量
     *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
     *        
     * @author Alexia
     * @date  2013-10-15
     */
    public class TransientTest {
    
        public static void main(String[] args) {
    
            User user = new User();
            user.setUsername("Alexia");
            user.setPasswd("123456");
    
            System.out.println("read before Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());
    
            try {
                ObjectOutputStream os = new ObjectOutputStream(
                        new FileOutputStream("C:/user.txt"));
                os.writeObject(user); // 将User对象写进文件
                os.flush();
                os.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                        "C:/user.txt"));
                user = (User) is.readObject(); // 从流中读取User的数据
                is.close();
    
                System.out.println("\nread after Serializable: ");
                System.out.println("username: " + user.getUsername());
                System.err.println("password: " + user.getPasswd());
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    
    class User implements Serializable {
        private static final long serialVersionUID = 8294180014912103005L;  
    
        private String username;
        private transient String passwd;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPasswd() {
            return passwd;
        }
    
        public void setPasswd(String passwd) {
            this.passwd = passwd;
        }
    
    }

    输出为:

    read before Serializable:
    username: Alexia
    password: 123456

    read after Serializable:
    username: Alexia
    password: null

    密码字段为null,说明反序列化时根本没有从文件中获取到信息。
    2. transient使用小结

    1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

    2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

    3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

    第三点可能有些人很迷惑,因为发现在User类中的username字段前加上static关键字后,程序运行结果依然不变,即static类型的username也读出来为“Alexia”了,这不与第三点说的矛盾吗?实际上是这样的:第三点确实没错(一个静态变量不管是否被transient修饰,均不能被序列化),反序列化后类中static型变量username的值为当前JVM中对应static变量的值,这个值是JVM中的不是反序列化得出的,不相信?好吧,下面我来证明:

    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    
    /**
     * @description 使用transient关键字不序列化某个变量
     *        注意读取的时候,读取数据的顺序一定要和存放数据的顺序保持一致
     *        
     * @author Alexia
     * @date  2013-10-15
     */
    public class TransientTest {
    
        public static void main(String[] args) {
    
            User user = new User();
            user.setUsername("Alexia");
            user.setPasswd("123456");
    
            System.out.println("read before Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());
    
            try {
                ObjectOutputStream os = new ObjectOutputStream(
                        new FileOutputStream("C:/user.txt"));
                os.writeObject(user); // 将User对象写进文件
                os.flush();
                os.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                // 在反序列化之前改变username的值
                User.username = "jmwang";
    
                ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                        "C:/user.txt"));
                user = (User) is.readObject(); // 从流中读取User的数据
                is.close();
    
                System.out.println("\nread after Serializable: ");
                System.out.println("username: " + user.getUsername());
                System.err.println("password: " + user.getPasswd());
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    
    class User implements Serializable {
        private static final long serialVersionUID = 8294180014912103005L;  
    
        public static String username;
        private transient String passwd;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPasswd() {
            return passwd;
        }
    
        public void setPasswd(String passwd) {
            this.passwd = passwd;
        }
    
    }

    运行结果为:

    read before Serializable:
    username: Alexia
    password: 123456

    read after Serializable:
    username: jmwang
    password: null

    这说明反序列化后类中static型变量username的值为当前JVM中对应static变量的值,为修改后jmwang,而不是序列化时的值Alexia。

    import java.io.Externalizable;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutput;
    import java.io.ObjectOutputStream;
    
    /**
     * @descripiton Externalizable接口的使用
     * 
     * @author Alexia
     * @date 2013-10-15
     *
     */
    public class ExternalizableTest implements Externalizable {
    
        private transient String content = "是的,我将会被序列化,不管我是否被transient关键字修饰";
    
        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(content);
        }
    
        @Override
        public void readExternal(ObjectInput in) throws IOException,
                ClassNotFoundException {
            content = (String) in.readObject();
        }
    
        public static void main(String[] args) throws Exception {
    
            ExternalizableTest et = new ExternalizableTest();
            ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                    new File("test")));
            out.writeObject(et);
    
            ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                    "test")));
            et = (ExternalizableTest) in.readObject();
            System.out.println(et.content);
    
            out.close();
            in.close();
        }
    }

    content变量会被序列化吗?好吧,我把答案都输出来了,是的,运行结果就是:
    1

    是的,我将会被序列化,不管我是否被transient关键字修饰

    这是为什么呢,不是说类的变量被transient关键字修饰以后将不能序列化了吗?

    我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。因此第二个例子输出的是变量content初始化的内容,而不是null。


    http://www.importnew.com/21517.html

    展开全文
  • 在java中指的是“一个类”可以“继承自”“另一个类”。 "被继承的类"叫做: 父类/超类/基类,"继承其他类的类"叫做:子类。 继承后,“子类”就“拥有”了“父类”所有的成员(成员变量、成员方法)。 “子类就不...

    1. 继承

    在java中指的是“一个类”可以“继承自”“另一个类”。 "被继承的类"叫做: 父类/超类/基类,"继承其他类的类"叫做:子类。
    继承后,“子类”中就“拥有”了“父类”中所有的成员(成员变量、成员方法)。 “子类就不需要再定义了”。
    

    继承的好处

    1. 提高代码的复用性(减少代码冗余,相同代码重复利用)。
    2. 使类与类之间产生了关系。
    3. 是多态的前提

    继承的格式

    class 父类 {
    	...
    }
    
    class 子类 extends 父类 {
    	...
    }
    

    需要注意:Java是单继承的,一个类只能继承一个直接父类,并且满足is-a的关系,例如:Dog is a Animal, Student is a Person

    继承后成员访问规则

    • 构造方法不能被继承

      public class Fu{
          public Fu(){
          }
          public Fu(String name,int age){
          }
      }
      public class Zi extends Fu{
      }
      public class Demo {
          public static void main(String[] args) {
              Zi z = new Zi("刘德华", 17);//编译错误,Zi类没有全参构造,不能完成对象的创建和对象数据的初始化
          }
      }
      
      

    继承后私有成员的访问规则

    • 父类的“私有成员”可以被子类继承,但子类不能被直接访问

      public class Fu{
          private int num = 100;//私有成员,只能在父类内部使用。
          private void method(){
              System.out.println("私有成员方法");
          }
      }
      public class Zi extends Fu{
      
      }
      public class Demo {
          public static void main(String[] args) {
              Zi z = new Zi();
      	    System.out.println(z.num);// 编译错误
              z.method();// 编译错误
          }
      }
      
      

    继承后非私有成员的访问规则

    • 当通过“子类”访问非私有成员时,先在子类中找,如果找到就使用子类的,找不到就继续去“父类”中找

      public class Fu{
          int money = 100;
          public void method(){
              System.out.println("Fu 类中的成员方法method");
          }
      }
      public class Zi extends Fu{
          int money = 1;
           public void method(){
              System.out.println("Zi 类中的成员方法method");
          }
      }
      public class Demo{
          public static void main(String[] args){
              Zi z = new Zi();
              System.out.println(z.money);//1
              z.method();// Zi 类中的成员方法method
          }
      }
      

    方法重写

    子类觉得父类的方法不够好

    方法重写 :子类中出现与父类一模一样的方法时(返回值类型,方法名和参数列表都相同),会出现覆盖效果,也称为重写或者复写。声明不变,重新实现

    public class Fu{
        public void eat(){
            System.out.println("我吃牛肉炖土豆...");
        }
    }
    public class Zi extends Fu{
    	@Override
        public void eat(){//方法重写
            System.out.println("我吃红烧狮子头...");
        }
    }
    //测试类
    public class Demo {
        public static void main(String[] args) {
            Zi zi = new Zi();
            zi.eat();// 我吃红烧狮子头...
        }
    }
    
    

    重写的注意事项

    • 子类方法重写父类方法,必须要保证权限大于等于父类权限

      • 访问权限从大到小: public protected (默认) private
    • 使用@Override注解,检验是否重写成功,重写注解校验!

      • 建议重写方法都加上这个注解,一方面可以提高代码的可读性,一方面可以防止重写出错!

    this和super关键字

    • this:存储的“当前对象”的引用;
      • this可以访问:本类的成员属性、成员方法、构造方法;
    • super:存储的“父类对象”的引用;
      • super可以访问:父类的成员属性、成员方法、构造方法;

    this关键字的三种用法

    • this访问本类成员变量: this.成员变量

      public class Student{
          String name = "张三";
          public void show(){
              String name = "李四";
              System.out.println("name = " + name);// 李四
              System.out.println("name = " + this.name);// 张三
          }
      }
      
      
    • this访问本类成员方法: this.成员方法名();

      public class Student{
          public void show(){
              System.out.println("show方法...");
              this.eat();
          }
          public void eat(){
              System.out.println("eat方法...");
          }
      }
      
      
    • this访问本类构造方法: this()可以在本类的一个构造方法中,调用另一个构造方法

      public class Student{
          public Student(){
              System.out.println("空参构造方法...");
          }
      
          public Student(String name) {
              this();//当使用this()调用另一个构造方法时,此代码必须是此构造方法的第一句有效代码。
              System.out.println("有参构造方法...");
          }
      }
      public class Demo {
          public static void main(String[] args) {
              Student stu2 = new Student();
          }
      }
      
      

    super关键字的三种用法

    • super访问父类的成员变量: super.父类成员变量名

      public class Fu{
          int money = 100;
      }
      public class Zi extends Fu{
          int money = 10;
          public void show(){
              int monet = 1;
              System.out.println(“money :+ money);//1
              System.out.println(“money :+ this.money);//10
              System.out.println(“money:” + super.money);//100 
          }
      }
      
      

      在这里插入图片描述

    • super访问父类的成员方法: super.成员方法名();

      public class Fu{
          public void show(){
              System.out.println("父类的show方法...");
          }
      }
      public class Zi extends Fu{
         public void show(){
              super.show();
              System.out.println("子类的show方法...");
          }
      }
      public class Demo {
          public static void main(String[] args) {
             Zi zi = new Zi();
             zi.show();
          }
      }
      
      
    • super访问父类的构造方法: super()

      public class Fu{
          public Fu(){
              System.out.println("Fu 类的空参构造方法..");
          }
          public Fu(String name, int age) {
              System.out.println("Fu 类的有参构造方法..");
          }
      }
      public class Zi extends Fu{
          public Zi(){
              super();// 调用父类的空参构造方法
              System.out.println("Zi 类的空参构造方法..");
          }
          public Zi(String name,int age){
              super(name,age);// 调用父类的有参构造方法
               System.out.println("Zi 类的有参构造方法..");
          }
      }
      public class Demo {
          public static void main(String[] args) {
              Zi zi = new Zi();
              System.out.println("----------------------");
              Zi z2 = new Zi("刘德华", 17);
          }
      }
      
      
      

    小结

    • this:存储的“当前对象”的引用;
      • this可以访问:本类的成员属性、成员方法、构造方法;
      • this.成员变量: 会遇到, setXxx() 和 有参构造, 自动生成
      • this.成员方法: 一般不会使用
      • this() : 一般不会使用, 可能会在源代码中遇到
    • super:存储的“父类对象”的引用;
      • super可以访问:父类的成员属性、成员方法、构造方法;
      • super.成员变量: 一般不会使用
      • super.成员方法: 子类重写父类的方法之后, 还想继续调用父类被重写的方法
      • super() : 在子类的构造方法中使用, 自动生成

    super的注意事项

    • 一、super访问成员变量和成员方法:优先去父类中找,如果有就直接使用,如果没有就去爷爷类中找,如果有,就用,依次类推…

      class Ye{
          int a = 10;
          public void eat(){
              System.out.println("Ye");
          }
      }
      class Fu extends Ye{
          int a = 20;
          public void eat(){
              System.out.println("Fu");
          }
      }
       class Zi extends Fu{
         int a = 30;
         public void show(){
             System.out.println(super.a);
             super.eat();
         }
      }
      public class Test2 {
          public static void main(String[] args) {
             Zi zi = new Zi();
             zi.show();
          }
      }
      
      
      
    • 二、子类的构造方法默认会调用父类的空参构造方法,如果父类中的没有空参构造方法,只定义了有参构造方法,会编译报错

      class Fu {
          public Fu(int a){
      
          }
      }
       class Zi extends Fu{// 编译报错
        
      }
      
      
      

    补充this和super的注意事项

    • this(参数)和super(参数), 必须出现在构造方法的第一行(第一条执行语句);
    • 构造方法中, this()和super()只能有一个.
    • this和super不能出现在static修饰的静态方法中

    继承体系对象的内存图

    • 继承体系内存图原理—父类空间优先于子类对象产生

      在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身。目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员。代码体现在子类的构造方法调用时,一定先调用父类的构造方法

    • 书写继承案例

      public class Fu {
          int num = 10;
          int numFu = 100;
      
          public void method(){
              System.out.println("父类中的method方法");
          }
      }
      public class Zi extends Fu {
      
          int num = 20;
      
          public void show(){
              int num = 30;
              System.out.println("访问局部变量num:"+num);
              System.out.println("访问本类成员变量num:"+this.num);
              System.out.println("访问父类成员变量num:"+super.num);
          }
      
          @Override
          public void method() {
              super.method();
              System.out.println("子类中的method方法");
          }
      }
      public class ExtendsDemo1 {
          public static void main(String[] args) {
              // 创建一个子类对象
              Zi zi = new Zi();
      
              // 使用子类对象调用show方法
              zi.show();
      
              // 使用子类对象调用method方法
              zi.method();
          }
      }
      
      
    • 根据案例绘制内存图

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bgkYviQo-1606538505376)(imgs\1574221685733.png)]

    2.抽象类

    抽象类的概述

    • 概述: 使用abstract关键字修饰的类就是抽象类
    • 特点: 这种类不能被创建对象,它就是用来做父类的,被子类继承的

    抽象类的定义

    • 格式:

      修饰符 abstract class 类名{
          
      }
      
      
    • 例如:

      public abstract class Person{
      
      }
      
      

    抽象类中的成员

    • 成员变量
    • 成员方法
    • 构造方法
    • 抽象方法

    抽象方法的定义

    修饰符 abstract 返回值类型 方法名(形参列表);
    例如:
    	public abstract void work();
    
    

    小结

    • 抽象方法: 没有方法体,使用abstract修饰的方法就是抽象方法

    • 抽象方法定义格式: 修饰符 abstract 返回值类型 方法名(形参列表);

    抽象类的特点

    • 抽象类不能被创建对象,就是用来做“父类”,被子类继承的。
    • 抽象类不能被创建对象,但可以有“构造方法”——为成员属性初始化
    • 抽象类中可以没有抽象方法,但抽象方法必须定义在抽象类中
    • 子类继承抽象类后,必须重写抽象类中所有的抽象方法,否则子类必须也是一个抽象类
    public abstract class Person {
        private String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public Person() {
        }
    
        public String getName() {
            return name;
        }
    
        // 抽象方法
        public abstract void eat();
        public abstract void drink();
    }
    
    public class Student extends Person {
        // alt+insert
        public Student(String name) {
            super(name);
        }
    
        @Override
        public void eat() {
            System.out.println("学生吃快餐...");
        }
    
        @Override
        public void drink() {
            System.out.println("学生喝冰红茶");
        }
    }
    
    public class Teacher extends Person {
        @Override
        public void eat() {
            System.out.println("老师吃小炒...");
        }
    
        @Override
        public void drink() {
            System.out.println("学生喝矿泉水");
        }
    }
    
    public abstract class Doctor extends Person{
        @Override
        public void eat() {
            System.out.println("医生吃麻辣烫");
        }
    }
    public class Test {
        public static void main(String[] args) {
           
            Student stu = new Student("张三");
            System.out.println(stu.getName());
        }
    }
    
    
    

    模板设计模式

    • 设计模式就是解决一些问题时的固定思路,也就是代码设计思路经验的总结。

    模板设计模式概述

    • 针对某些情况,在父类中指定一个模板,然后根据具体情况,在子类中灵活的具体实现该模板
    public abstract class Person{
        // 睡觉,所有子类实现都是一样的  有方法体的方法
        public void sleep(){/
            // 所有子类通用的实现方式
            System.out.println("两眼一闭,直接睡觉...");
        }
        
        // 吃东西,所有子类是不一样的实现,但是都有吃东西的功能
        public abstract void eat();
    }
    
    
    • 抽象类体现的就是模板思想模板是将通用的东西在抽象类中具体的实现,而模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求

    模板模式的实现步骤

    • 定义抽象父类作为模板
    • 在父类中定义"模板方法"— 实现方法(模板)+抽象方法(填充模板)
    • 子类继承父类,重写抽象方法(填充父类的模板)
    • 测试类:
      • 创建子类对象,通过子类调用父类的“实现的方法”+ “子类重写后的方法” e

    案例演示

    假如我现在需要定义新司机和老司机类,新司机和老司机都有开车功能,开车的步骤都一样,只是驾驶时的姿势有点不同,新司机:开门,点火,双手紧握方向盘,刹车,熄火老司机:开门,点火,右手握方向盘左手抽烟,刹车,熄火。那么这个时候我们就可以将固定流程写到父类中,不同的地方就定义成抽象方法,让不同的子类去重写

    分析:

    • 定义司机类作为模板(抽象类)
      • 开车功能(通用功能,有方法体的方法)
        • 开门
        • 点火
        • 调用开车姿势的方法(新老司机的姿势是不一样的)
        • 刹车
        • 熄火
      • 开车姿势的抽象方法(供子类重写)
    • 新司机,继承司机类,重写开车姿势的方法
    • 老司机,继承司机类,重写开车姿势的方法

    代码如下:

    // 司机开车的模板类
    public abstract class Driver {
        public void go() {
            System.out.println("开门");
            System.out.println("点火");
            // 开车姿势不确定?定义为抽象方法
            ziShi();
            System.out.println("刹车");
            System.out.println("熄火");
        }
    
        public abstract void ziShi();
    }
    
    

    现在定义两个使用模板的司机:

    public class NewDriver extends Driver {
    
        @Override
        public void ziShi() {
            System.out.println("新司机双手紧握方向盘");
        }
    }
    
    public class OldDriver extends Driver {
        @Override
        public void ziShi() {
            System.out.println("老司机右手握方向盘左手抽烟...");
        }
    }
    
    

    编写测试类

    public class Demo02 {
        public static void main(String[] args) {
            NewDriver nd = new NewDriver();
            nd.go();
    
            OldDriver od = new OldDriver();
            od.go();
        }
    }
    
    

    运行效果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1aExobRj-1606538505380)(imgs/1560747035458.png)]

    可以看出,模板模式的优势是,模板已经定义了通用架构,使用者只需要关心自己需要实现的功能即可!非常的强大!

    小结

    • 抽象类存在的意义是为了被子类继承,否则抽象类将毫无意义,抽象类体现的是模板思想模板是将通用的东西在抽象类中具体的实现,而模板中不能决定的东西定义成抽象方法,让使用模板(继承抽象类的类)的类去重写抽象方法实现需求,这是典型的模板思想

    3. final关键字

    final不可改变。可以用于修饰类、方法和变量。

    • 类:被修饰的类,不能被继承
    • 方法:被修饰的方法,不能被重写
    • 变量:被修饰的变量,就只能赋值一次,不能被重新赋值

    final关键字的使用

    修饰类

    格式如下:

    修饰符 final class 类名 {
      
    }
    例如:
    public final class FinalClassFu {
    }
    public class FinalClassZi /*extends FinalClassFu*/ {
        // FinalClassFu类被final修饰了,所以不能被继承
    }
    
    

    查询API发现像 public final class Stringpublic final class Mathpublic final class Scanner 等,很多我们学习过的类,都是被final修饰的,目的就是供我们使用,而不让我们所以改变其内容

    修饰方法

    格式如下:

    修饰符 final 返回值类型 方法名(参数列表){
        //方法体
    }
    
    

    重写被 final修饰的方法,编译时就会报错。

    public class FinalMethodFu {
        public final void show(){
    
        }
    }
    public class FinalMethodZi extends FinalMethodFu {
    
        /*@Override
        public void show() {
    
        }*/
        // 无法重写父类中的show方法,因为父类中的show方法被final修饰了
    }
    
    
    修饰变量
    局部变量——基本类型

    基本类型的局部变量,被final修饰后,只能赋值一次,不能再更改。代码如下:

    public class FinalDemo1 {
        public static void main(String[] args) {
            // 声明变量,使用final修饰
            final int A;
            // 第一次赋值 
            A = 10;
            // 第二次赋值
            A = 20; // 报错,不可重新赋值
        }
    }
    
    
    局部变量——引用类型

    引用类型的局部变量,被final修饰后,只能指向一个对象,地址不能再更改。但是不影响对象内部的成员变量值的修改,代码如下:

    public class FinalDemo2 {
        public static void main(String[] args) {
            // 创建 User 对象
            final User U = new User();
            
            // 创建 另一个 User对象
            // U = new User(); // 报错,指向了新的对象,地址值改变。
    
            // 调用setName方法
            U.setName("张三"); // 可以修改
        }
    }
    
    
    
    成员变量

    成员变量涉及到初始化的问题,初始化方式有两种,只能二选一:

    1. 显示初始化

      public class FinalVariable {
          final int NUM1 = 10;
      }
      
      

    2.== 构造方法初始化==。

    public class FinalVariable {
        final int NUM2;
        public FinalVariable(int NUM2){
            this.NUM2 = NUM2;
        }
        public FinalVariable(){
            this.NUM2 = 10;
        }
    }
    
    

    被final修饰的常量名称,一般都有书写规范,所有字母都大写

    小结:

    • final修饰类,类不能被继承。
    • final修饰方法,方法不能被重写。
    • final修饰变量,变量不能被改值。
    展开全文
  • javatransient关键字简介

    千次阅读 2015-01-12 15:56:18
    我们都知道一个对象只要实现了 Serilizable 接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和...

    java中 transien 关键字

    我们都知道一个对象只要实现了 Serilizable 接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化。

           然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,诚然,你可以让这个类来实现Externalizable接口,这个接口是Serilizable的子接口,但是你必须实现 readExternal 和 writeExternal 方法,你可以在这两个方法中实现具体属性的反序列化和序列化操作。然而这就意味着你必须在这两个方法中手工编写额外的代码来进行具体属性的序列化。java的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

    public class TestTransient {
    
    /**
    * @param args
    * @throws IOException 
    * @throws FileNotFoundException 
    * @throws ClassNotFoundException 
    */
    public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
       A a = new A(25,"张三");
       System.out.println(a);
       ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c://mm.txt"));
       oos.writeObject(a);
       oos.close();
       ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c://mm.txt"));
       a = (A)ois.readObject();
       System.out.println(a);
    
    }
    
    }
    
    class A implements Serializable{
    int a;
    transient String b;
    public A(int a,String b){
       this.a = a;
       this.b = b;
    }
    public String toString(){
       return "a = "+a+",b = "+b;
    }
    }

    运行结果如下:

    a = 25,b = 张三
    a = 25,b = null


    在上面的例子中,将属性b前添加关键字transient,我们看到虽然我们序列化的对象a的属性值为“张三”,

    但是当我们反序列化之后发现这个属性为空,说明这个属性没有进行序列化。


    展开全文
  • javatransient关键字

    2017-01-16 21:43:29
    transient是Java语言的关键字,变量修饰符,如果用它声明一个实例变量,当对象存储时,它的值不需要维持。 在java中一个对象只要实现了Serializable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供...
    • transient是Java语言的关键字,变量修饰符,如果用它声明一个实例变量,当对象存储时,它的值不需要维持。
    • 在java中一个对象只要实现了Serializable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serializable接口,这个的所有属性和方法都会自动序列化
    • 在实际开发过程中,通常是某个类(Bean)的某些些属性需要序列化,而其他属性不需要被序列化,你可以让这个类来实现Externalizable接口,这个接口是Serializable的子接口,但是你必须实现readExternalwriteExternal方法,你可以在这两个方法中实现具体属性的反序列化和序列化操作。这就意味着你必须在这两个方法中手工编写额外的代码来进行具体属性的序列化。这时transient就派上用场了,你只需要实现Serializable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
    import java.io.Serializable;
    public class Car implements Serializable{
        private static final long serialVersionUID = 6342094113290306717L;
        private transient String carName; //用transient修饰的属性,不会被序列化
        private String carBrand;
        private transient String cash; //用transient修饰的属性,不会被序列化
        private Integer count;
        //Getters  Setters
    }
    
    展开全文
  • 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化...
  • 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化...
  • java的transient关键字

    2018-05-13 13:00:34
    我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法...
  • 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化...
  • 一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java的这种序列化模式为开发者提供了很多便利,可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个的所有属性和方法都会自动序列化...
  • JavaTransient关键字

    2019-01-20 11:59:00
    我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和...
  • java的Transient关键字

    2015-06-22 20:50:49
    1. transient的作用及使用方法我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了...
  • 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和...
  • Linux vi 搜索关键字

    2013-09-05 16:00:00
    当你用vi打开一个文件后,因为文件太长,如何才能找到你所要查找的关键字呢? 在vi里可没有菜单-〉查找 不过没关系,可以在命令模式下敲斜杆( / )这时在状态栏(也就是屏幕左下脚)就出现了 “/” 然后输入你要...
  • 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和...
  • 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和...
  • transient的作用及使用方法我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable...
  • java 关键字

    2016-09-14 18:40:07
    transient关键字www.baidu.com ilizable接口,这个对象就可以被序列...然而在实际开发过程,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏...
  • this关键字

    2018-03-07 11:05:45
    函数的this,this的指向与定义和执行位置没有关系,只关注函数执行前面是否有“.”,有的话则指向“.”前面的对象,如果有多“.”,指向最近的那个点前面的对象(上级对象),没有的话指向window,严格模式是...
  • 计算候选关键字

    万次阅读 2015-09-07 02:28:31
    1、已知关系R(A,B,C,D,E)及其上的函数相关性集合,F={A→B,E→A,CE→D},该关系的候选...属性: 表的一列即为一个属性 2、形式化定义 关系定义2.3: n目关系必有n目关系 二、候选关键字 候选关键字:候选码,关系中
  • transient关键字

    2019-09-26 06:01:30
    我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 596
精华内容 238
关键字:

关系模式中一个关键字