整理02
1.以下程序分别执行后,输出的结果是什么?
public class A{ public static int a = 6; } 第一次 public class Test1{ public static void main(String[] args){ A a1 = new A(); a1.a ++; System.out.println(a1.a); } } 第二次 public class Test2{ public static void main(String[] args){ A a2 = new A(); System.out.println(a2.a); } }
第一次运行输出7,这大家应该都明白,那第二次运行输出什么呢,6or7? 答案是6,大家会有疑问了,同一个类的所有实例的静态变量共享同一块内存区域吗,但是这句话有个重要前提,在同一个JVM进程中,上述两次执行的程序运行在不同的JVM进程中,不同进程之间不会共享数据。
2.一些易忽略的问题总结
- 静态方法中不能调用非静态的成员或成员方法:
public class A { int a; public static void main(String[] args) { a = 2;//错误!!a非静态 } }
- protected修饰的构造器在包内部可以被new实例,在其他包非子类中不能被new实例。其他包子类可以访问(包括匿名类):
- 抽象类是以abstract修饰的类,这个类里面可以有抽象的方法也可以没有!!
- final 修饰的变量,其引用的对象不可以改变,但是我们可以改变对象的内容。
public static void main(String[] args) { final Person p = new Person ( "zhangsan" ,11); p.setAge(12);//可以 System. out .println(p.getAge()); // p = new Person(" lisi ",22); //错误 }
- JAVA类不支持多重继承,为了克服这个缺点,引入了接口的概念。
- final修饰的类不能被继续,同理,修饰的方法也不能被重写。
3.JAVA的作用域有哪些,这四个分别说说
作用域 | 当前类 | 同一个package | 子孙类 | 不同package |
public | 是 | 是 | 是 | 是 |
protected | 是 | 是 | 是 | 否 |
private | 是 | 否 | 否 | 否 |
friendly | 是 | 是 | 否 | 否 |
不写的话,默认为friendly; private
和protected一般不
用于修饰外部类.
如果类可以使用private来修饰,表示该包下的这个类不能被其它类访问,那么该类也失去了存在的意义,所以不能使用private来修饰类。
如果类可以使用protected来修饰,表示该类所在的包的其它类可以访问该类;该类所在的包的子包的类可以访问该类,但是包没有继承的概念,所以后一句是不对。所以用protected来修饰类也是没有意义的。
4.JAVA语言的优点
1、Java是纯面向对象的语言。《Java编程思想》中提到Java语言是一种“Everything is object”的语言,它能够直接反映现实生活中的对象,例如车、动物等,因此通过它编写程序更容易。
2、平台无关性。Java语言可以“一次编译,到处执行”。无论是在Windows平台还是在Linux、MacOS等其他平台上对Java程序进行编译,编译后的程序在其他平台上都可以运行。由于Java是解释性语言,编译器会将Java代码变成“中间代码”,然后在Java虚拟机(Java Virtual Machine,JVM)上解释执行。由于中间代码与平台无关,因此Java语言可以很好的跨平台执行,具有很好的可移植性。
3、Java提供了很多内置的类库,通过这些类库,简化了开发人员的程序设计工作,同时缩短了项目的开发时间,例如,Java语言提供了对多线程的支持,提供了对网络通信的支持,最主要的是提供了垃圾回收器,这使得开发人员从内存的管理中解脱出来。
4、提供了对Web应用开发的支持。例如,Applet、Servlet和JSP可以用来开发Web应用程序;Socket、RMI可以用来开发分布式应用程序。
5、具有较好的安全性和健壮性。Java语言经常被用在网络环境中,为了增强程序的安全性,Java语言提供了一个防止恶意代码攻击的安全机制(数组边界检测和Bytecode校验等)。Java的强类型机制、垃圾回收器、异常处理和安全检查机制使得用Java语言编写的程序具有很好的健壮性。
6、去除了C++语言中难以理解、容易混淆的特性,如头文件、指针、结构、单元、运算符重载、虚拟基础类、多重继承等,使得程序更加严谨简洁。
5.为什么JAVA有的接口没有定义任何方法
我们来先了解下接口有哪些特征:
1.接口是抽象方法定义的集合,是一种特殊的抽象类。
2.只包含方法的定义、不能有方法的实现。
3.可以包含方法也可以包含常量。
4.所有方法都是抽象的。
5.成员的作用域修饰符都是public,常量的默认修饰符是public static final,
没有定义任何方法的接口 又被称作标识接口,继承此接口的类被打上相应的标签,比如序列化接口Serializable,就是标识接口。
6.序列化是什么?什么时候应该序列化?
- 序列化是什么
- 简单的来说就是保存内存中对象的信息(不包括方法),并且可以把保存的对象状态再读出来。虽然你可以用你自己的各种各样的方法来保存object states,但是Java给你提供一种应该比你自己好的保存对象状态的机制,那就是序列化。
- 什么时候应该序列化
- 当你想把内存中的对象信息保存到文件中或者数据库。
- 当想用套接字在网络上传递对象
- 当你想使用RMI(remote method invocation)传输对象时。
由上可知,序列化的关键是对象。对象是保存在堆上的。
若类中某个字段不想被序列化,定义的时候加上transient,transient关键字只能修饰变量,不能修饰方法和类。静态变量不能被序列化。
继续深入一个问题,被transient修饰的字段真的不能在序列化输出了吗,参考下面的例子
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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变量会被序列化吗?好吧,我把答案都输出来了,是的,运行结果就是:
是的,我将会被序列化,不管我是否被transient关键字修饰
这是为什么呢,不是说类的变量被transient关键字修饰以后将不能序列化了吗?
我们知道在Java中,对象的序列化可以通过实现两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。因此第二个例子输出的是变量content初始化的内容,而不是null。
参考:http://blog.csdn.net/lisulong1/article/details/52269262