Java 基础常识
- Java 的跨平台是通过什么实现的?
答:java跨平台是通过JVM(java 虚拟机)实现的。java 虚拟机:即Java Virtual Machine
但JVM(java虚拟机)不是跨平台的, sun公司针对不同的平台分别设计不同的JVM 。
注意:编译的结果不是生成机器码,而是生成字节码,字节码不能直接运行,必须通过
JVM翻译成机器码才能运行。不同平台下编译生成的字节码是一样的,但是由JVM翻译
成的机器码却不一样。 - JDK、JRE、JVM 的全称是什么?
答: JDK(Java Development Kit) 是 Java 语言的软件开发工具包; JRE(Java Runtime En
vironment,Java运行环境),运行JAVA程序所必须的环境的集合,包含JVM标准实现及
Java核心类库; JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计
算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算
机功能来实现的。 - public class 的类名必须跟文件名保持一致吗?
答: 1.java保存的文件名必须与类名一致;
2.如果文件中只有一个类,文件名必须与类名一致;
3.一个Java文件中只能有一个public类;
4.如果文件中不止一个类,文件名必须与public类名一致;
5.如果文件中不止一个类,而且没有public类,文件名可与任一类名一致。 - 一个 Java 源文件可以写多个 Class 吗?编译后会不会生成多个 Class 文件?
答: 一个JAVA源文件里面可以有内部类,其他类(有且仅有一个类可以声明为public),所以,
编译后,可以有多个class文件。 - 编程时,为什么需要注释?Java 中注释的类型有哪些?
答: 1. 应用编码规范对于软件本身和软件开发人员而言尤为重要,其中注释就是非常重要的一部
分了。你的注释不仅仅可以帮助你理解代码含义,还有利于测试人员测试代码,更加重要的
是它在后期生成文档,下一次看代码可以节约不少时间和精力。
2.对于Java注释我们主要了解三种: 1. // 注释一行 2./* …… / 注释若干行 3./*……*/文档
注释 /* …… / 注释若干行,并写入 javadoc文档,java图标通常这种注释的多行写法如下:
/* ……… * ……… */
面向对象(一)
简述面向对象和面向过程的区别和联系?
答: 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候
一个一个依次调用就可以了。 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是
为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。 面向过程的编程应
该关注的是如何使用函数去实现既定的功能。面向对象的编程,是关注如何把相关的功能,包括
函数和数据有组织地捆绑到一个对象身上。例如五子棋,面向过程的设计思路就是首先分析问题
的步骤:1、开始游戏,2、黑子先走,3、绘制画面,4、判断输赢,5、轮到白子,6、绘制画面
7、判断输赢,8、返回步骤2,9、输出最后结果。把上面每个步骤用分别的函数来实现,问题就
解决了。 而面向对象的设计则是从另外的思路来解决问题。整个五子棋可以分为 1、黑白双方,
这两方的行为是一模一样的,2、棋盘系统,负责绘制画面,3、规则系统,负责判定诸如犯规、
输赢等。第一类对象(玩家对象)负责接受用户输入,并告知第二类对象(棋盘对象)棋子布局
的变化,棋盘对象接收到了棋子的i变化就要负责在屏幕上面显示出这种变化,同时利用第三类对
象(规则系统)来对棋局进行判定。可以明显地看出,面向对象是以功能来划分问题,而不是步骤。
同样是绘制棋局,这样的行为在面向过程的设计中分散在了总多步骤中,很可能出现不同的绘制版
本,因为通常设计人员会考虑到实际情况进行各种各样的简化。而面向对象的设计中,绘图只可能
在棋盘对象中出现,从而保证了绘图的统一。 功能上的统一保证了面向对象设计的可扩展性。比如
我要加入悔棋的功能,如果要改动面向过程的设计,那么从输入到判断到显示这一连串的步骤都要
改动,甚至步骤之间的循序都要进行大规模调整。如果是面向对象的话,只用改动棋盘对象就行了
,棋盘系统保存了黑白双方的棋谱,简单回溯就可以了,而显示和规则判断则不用顾及,同时整个
对对象功能的调用顺序都没有变化,改动只是局部的。
再比如我要把这个五子棋游戏改为围棋游戏,如果你是面向过程设计,那么五子棋的规则就分布在
了你的程序的每一个角落,要改动还不如重写。但是如果你当初就是面向对象的设计,那么你只用
改动规则对象就可以了,五子棋和围棋的区别不就是规则吗?(当然棋盘大小好像也不一样,但是
你会觉得这是一个难题吗?直接在棋盘对象中进行一番小改动就可以了。)而下棋的大致步骤从面
向对象的角度来看没有任何变化。 当然,要达到改动只是局部的需要设计的人有足够的经验,使用
对象不能保证你的程序就是面向对象,初学者或者很蹩脚的程序员很可能以面向对象之虚而行面向
过程之实,这样设计出来的所谓面向对象的程序很难有良好的可移植性和可扩展性。
这两种不同的设计思想使得在运用这两种思想编程时粒度相差很大:面向对象的程序单位是类,而
面向过程的 程序单位是函数,使得它比面向对象过程更复杂。
而两者的联系又体现在都是在对数据进行处理,只是面向对象站在更高的角度上,将数据和函数打
包,在对象的层次上去处理。
实际实现一个 对象的过程中,就包含了很多面向过程的方法。
来源: https://zhidao.baidu.com/question/587576019136886805.html对象和类的关系时?
答: 对象是对客观事物的抽象,类是对对象的抽象。类是一种抽象的数据类型,其定义为:class 类名{ }
它们的关系是,对象是类的实例,类是对象的模板。- 堆和栈的特点是什么?分别存放什么内容?
答: 堆――heap;栈――stack;栈是机器系统提供的数据结构,而堆是由C/C++函数库提供的;1、从
数据结构层次理解,栈是一种先进后出的线性表,只要符合先进后出的原则的线性表都是栈。至于采
用的存储方式(实现方式)是顺序存储(顺序栈)还是链式存储(链式栈)是没有关系的。堆则是二
叉树的一种,有最大堆最小堆,排序算法中有常用的堆排序。2、 从系统层次理解,栈是系统为运行
的程序分配的先进后出的存储区域。在学习bootloader时知道,在上电后初始化阶段要为各个工作模
式下分配堆 栈,这里的堆栈实际上就是指stack,堆栈的说法只是因为历史的原因。在执行函数时,
函数内部局部变量的存储单元可以在栈上创建(针对CISC架构而 言,RISC架构下,局部变量的存储
单元是在寄存器上创建),函数执行结束时这些存储单元自动被释放。堆是系统管理的可以被程序利
用的全局存储空间,动态 内存分配就是从堆上分配。
总结:
1、栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是函数库提供的功能,
特点是灵活方便,数据适应面广泛,但是效率有一定降低。
2、栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一,不同堆分
配的内存无法互相操作。
3、栈空间分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动
态分配由alloc函数完成。栈的动态分配无需释放 (是自动的),也就没有释放函数。为可移植的
程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的
数据空间都会被释放 回系统,但是精确的申请内存/释放内存匹配是良好程序的基本要素。
来源: http://blog.csdn.net/yahohi/article/details/8035996 - 局部变量使用之前,需要手动初始化吗?
答:成员变量可以不用初始化,其具有默认值;但是局部变量一定需要初始化或者赋值后才能使用,否则编
译报错。
可能的原因如下,当我们新建一个对象时,Java会在Heap中申请一块内存区域用以存放类的数据。而
成员变量就是类的数据,也是放在这块内存区域中的。只需要JVM在申请内存的时候顺便把整块区域都
置为零即可完成初始化,方便快捷。而对于方法的局部变量,是在线程的Stack中,当然Stack他也可以
帮我们初始化,不过有一个问题。对于有些局部变量,在方法的一开始是没有的,有些在循环中的局部
变量是要反复的声明多次的。有些局部变量作用域结束后,另一个局部变量又会占用这个局部变量的位
置。
来源: http://blog.csdn.net/rockpk008/article/details/52124461 - Java 中如果不手动指定成员变量的值,系统会自动初始化,那么初始化的规则是?
答:
基本数据类型 默认值
byte 0
short 0
int 0
long 0L
char \u0000(空格)
float 0.0f
double 0.0d
boolean false
所有引用类型的初始化值为null。 class interface array;
注意:java自己不会执行局部变量的初始化,需要人为赋值,才可以使用。
但是,定义一个局部的数组: int[] arr =new int[5] ;
其中的元素也被赋上默认初始值,打印结果为0,看来数组还真是不简单。
百度后发现和new关键字有关,并且需要掌握内存中的栈和堆。原来,内存
中分为堆内存和栈内存,程序开始时,main方法进栈,在堆内存中分配空间
创建的成员变量;局部变量保存在栈中。 创建数组则是在堆中,分配空间后
默认初始化值。 我觉得可以这样认为,在堆内存中分配空间的变量都会java
都会自动初始化值,像成员变量。
- 构造方法如何被调用?
答:新建一个对象是被调用。也就是new的时候;如:
public class A {
int i;
String c;
public A() { } //无参构造方法
public A (int i, String c) { // 两参构造方法
this.i = i;
this.c = c;
}
public static void main(String[] args) {
A a = new A() ; //调用了无参构造方法;
A a1 = new A(5,”vieri”); //调用了两参构造方法
}
}
来源: http://blog.csdn.net/woshixuye/article/details/7214976 - 系统一定会给我们添加无参数的构造方法吗?请详细解释。
答: 每个类在没有声明构造方法的前提下,会自动生成一个不带参数的构造方法,如果
类一但声明有构造方法,就不会产生了.
可证:
class person
{
person(){System.out.println(“父类-person”);}
person(int z){}
}
class student extends person
{
// student(int x ,int y){super(8);}
}
class Rt
{
public static void main(String[]args)
{
student student_dx=new student();//创建student类的对象
}
}
//输出结果:父类-person
来源: http://blog.csdn.net/stellaah/article/details/6718178
例说明:student类自动生成student() {super();}(前提是:student类没有声明构造方法的前提下) ‘super()’是用来调用父类的构造方法.
- 构造方法能不能重载?
答: 可以,同名不同参
- this 在普通方法中,指的是哪个对象?在构造方法中,指的是?
答: this 在普通方法中,指的是调用该方法的对象,在构造方法中,指的是调用该构造方法的对象。
- 静态初始化块和 main 方法哪个先被执行?
答: 静态初始化块比main方法先执行;
补充:
所有的静态初始化块都优先执行,其次才是非静态的初始化块和构造函数,它们的执行顺序是
父类的静态初始化块子类的静态初始化块父类的初始化块父类的构造函数子类的初始化块子类
的构造函数,静态代码块是:属于类的,在类加载时就自动执行。静态代码块定义时不能添加
作用域符。构造块是: 在类中定义的,且定义的位置与该类的其他的属性是相当的,就是不在
该类的任何成员方法中,定义时直接用{ }包含即可,不用再添加其他任何的访问作用域符。构
造块是每次创建对象都会执行一次构造块。普通代码块:定义位置实在方法内部,在方法体内
用 { } 包含即可。
一个构造方法调用另一个构造方法怎么调用?this() 这样的调用方式必须位于第一句吗?
答: this或者super;实例方法中可以使用this关键字,它指向正在执行方法的类的实例对象,当然static
方法中是不可以使用this对象的,因为静态方法不属于类的实例对象;而构造方法中同样可以使用
this关键字,构造器中的this是指向同一个对象中不同参数的另一个构造器。
public class Platypus {
String name;Platypus(String input) {
name = input;
}Platypus() {
this(“John/Mary Doe”);
}public static void main(String args[]) {
Platypus p1 = new Platypus(“digger”);
Platypus p2 = new Platypus();
System.out.println(p1.name + “—-” + p2.name);
}
}
上面的代码中 类有两个构造器,第一个构造器给类的成员name赋值,第二个构造器调用第一个构造器给类
的成员name一个初始值Jonn/Mary Doe
所以程序执行结果:digger—-John/Mary Doe
需要注意的两个地方是:
1、构造方法中通过this关键字调用其他构造方法时,那么这句代码必须放在第一行,否则会编译错误。
2、构造方法中只能通过this调用一次其他的构造方法。”super”的用法:
实例方法和构造方法中的super关键字都用于去指向父类,实例方法中的super关键字是去调用父类当中的某个方法,看
下面的代码:
class getBirthInfo {
void getBirthInfo() {
System.out.println(“born alive.”);
}
}
class Platypus1 extends getBirthInfo
{
void getBirthInfo() {
System.out.println(“hatch from eggs”);
System.out.println(“a mammal normally is “);
super.getBirthInfo();
}
}
public class test1 {
public static void main(String[] args) {
Platypus1 p1=new Platypus1();
p1.getBirthInfo();
}
}
上面的例子使用super.getBirthInfo();调用了它的父类的void getBirthInfo()方法。
构造器中使用super关键字调用父类中的构造器,看下面的代码:
class getBirthInfo {
getBirthInfo(){
System.out.println(“auto”);
}
void aa() {
System.out.println(“born alive.”);
}
}
class Platypus1 extends getBirthInfo
{
Platypus1() {
super();
System.out.println(“hatch from eggs”);
System.out.println(“a mammal normally is “);
}
}
public class test1 {
public static void main(String[] args) {
Platypus1 p1=new Platypus1();
}
}
执行了代码我们就会看到构造器中的super调用了父类的构造方法。
类的继承机制使得子类可以调用父类的功能,下面介绍类在继承关系的初始化顺序问题
请看实例1:
class SuperClass
{
SuperClass()
{
System.out.println(“SuperClass constructor”);
}
}
public class SubClass extends SuperClass {
SubClass()
{
System.out.println(“SubClass constructor”);
}
public static void main(String[] args) {
SubClass sub = new SubClass();
}
}
执行结果:SuperClass constructor
SubClass constructor
代码中我们只实例化子类一个对象,但从执行结果上看程序一开始并不是运行子类的构造方法,而是先执行父类的默认构造方法,然后再执行子类的构造方法.所以我们在实例化子类对象时,程序会先调用父类的默认构造方法,然后再执行子类的构造方法。
再看实例2:
class SuperClass
{
SuperClass(String str)
{
System.out.println(“Super with a string.”);
}
}
public class SubClass extends SuperClass
{
SubClass(String str)
{
System.out.println(“Sub with a string.”);
}
public static void main(String[] args)
{
SubClass sub = new SubClass("sub");
}
}
注意:此程序在JDK下不能编译成功,因为我们在实例化子类对象的时候会先调用其父类默认的构造方法(除非实例化对象的构造函数中有调用任意的父类构造方法),但是它的父类没有默认的构造方法,所以不能编译成功。易错地方!!
解决办法:
1、在父类中加一个显示的默认构造方法
2、在子类的构造方法中加一句super(str)并且必须在构造器的第一句。
两个办法都可以解决程序编译的问题,但是执行结果是不一样的.
第一种执行结果为:Sub with a string.
第二种执行结果为:Super with a string.
Sub with a string. 第二种方法即使父类中有显示的默认构造方法也不会被调用。
- package 的两个作用是什么?
答:
1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
- import statis 叫做静态导入,那么其作用是什么?
答: 导入静态成员;import static静态导入是JDK1.5中的新特性。一般我们导入一个类都用 import com…..ClassName;而静态导入是这样:import static com…..ClassName.*;这里的多了个
static,还有就是类名ClassName后面多了个 .* ,意思是导入这个类里的静态方法。当然,也可
以只导入某个静态方法,只要把 .* 换成静态方法名就行了。然后在这个类中,就可以直接用方法名
调用静态方法,而不必用ClassName.方法名 的方式来调用。
这种方法的好处就是可以简化一些操作,例如打印操作System.out.println(…);就可以将其写入一个静态方法print(…),在使用时直接print(…)就可以了。 在静态导入之前:
public class TestStatic {
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
System.out.println(Integer.toHexString(42));
}
}
在静态导入之后:
import static java.lang.System.out;
import static java.lang.Integer.*;
public class TestStaticImport {
public static void main(String[] args) {
out.println(MAX_VALUE);
out.println(toHexString(42));
}
}
两个类都产生相同的输出:
2147483647
2a
来源: http://blog.sina.com.cn/s/blog_764e06170101ahrq.html
但是这种方法建议在有很多重复调用的时候使用,如果仅有一到两次调用,不如直接写来的方便
来源: http://www.cnblogs.com/lushilin/p/5288860.html
- 请详细快速的说明 private、default、protected、public 的区别。
答:
修饰符 类内部 本包 子类 外部包
public √ √ √ √
protected √ √ √ X
default √ √ X X
private √ X X X
- javabean 就是只包含属性和相关 getter/setter 方法,不包含业务逻辑处理的被,这种说法对吗?
答: 可以包含;
JavaBean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可
以很容易的被重用或者是插入其他应用程序中去。所有遵循“一定编程原则”的Java类都可以
被称作JavaBean。
◆JavaBean是一个遵循特定写法的Java类,是一种Java语言编写的可重用组件,它的方法命
名,构造及行为必须符合特定的约定:
1、这个类必须具有一个公共的(public)无参构造函数;
2、所有属性私有化(private);
3、私有化的属性必须通过public类型的方法(getter和setter)暴露给其他程序,并且方法的
命名也必须遵循一定的命名规范。
4、这个类应是可序列化的。(比如可以实现Serializable 接口,用于实现bean的持久性)
◆JavaBean在Java EE开发中,通常用于封装数据,对于遵循以上写法的JavaBean组件,其它程序可以通过反射 技术实例化JavaBean对象(内省机制),并且通过反射那些遵循命名规范的方法,从而获知JavaBean的属性, 进而调用其属性保存数据。
因为这些要求主要是靠约定而不是靠实现接口,所以许多开发者把JavaBean看作遵从特定命名约定的POJO。(可以这么理解,POJO按JavaBean的规则来,就可以变成JavaBean)。
◆简而言之,当一个POJO可序列化,有一个无参的构造函数,使用getter和setter方法来访问属性时,他就是一个JavaBean。(没毛病!)
JavaBean是一种组件技术,就好像你做了一个扳手,而这个扳手会在很多地方被拿去用,这个扳子也提供多种功能(你可以拿这个扳手扳、锤、撬等等),而这个扳手就是一个组件。
◇对于JavaBean,就是一个Java模型组件,他为使用Java类提供了一种标准的格式,在用户程序和可视化管理工具中可以自动获得这种具有标准格式的类的信息,并能够创建和管理这些类。
◇JavaBean可以使应用程序更加面向对象,可以把数据封装起来,把应用的业务逻辑和显示逻辑分离开,降低了开发的复杂程度和维护成本!
◇JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBeans 通过提供符合一致性设计模式的公共方法将内部域暴露称为属性。众所周知,属性名称符合这种模式,其他Java 类可以通过内省机制发现和操作这些JavaBean 属性。
◇通常情况下,由于 Java Bean 是被容器所创建(如 Tomcat) 的,所以 Java Bean 应具有一个无参的构造器,另外,通常 Java Bean 还要实现 Serializable 接口用于实现 Bean 的持久性。 Java Bean 是不能被跨进程访问的。
◇JavaBean 是使用 java.beans 包开发的,它是 Java 2 标准版的一部分。JavaBean 是一台机器上同一个地址空间中运行的组件。JavaBean 是进程内组件。
来源: http://blog.csdn.net/chenchunlin526/article/details/69939337#comments
-构造方法和实例方法的区别
答:主要的区别在于三个方面:修饰符、返回值、命名
1、和实例方法一样,构造器可以有任何访问的修饰符,public、private、protected或者
没有修饰符,都可以对构造方法进行修饰。不同于实例方法的是构造方法不能有任何
非访问性质的修饰符修饰,例如static、final、synchronized、abstract等都不能修
饰构造方法。
解释:构造方法用于初始化一个实例对象,所以static修饰是没有任何意义的;多个线程不会同时创建内存地 址相同的同一个对象,所以synchronized修饰没有意义;
构造方法不能被子类继承,所以final和abstract修饰没有意义。
2、返回类型是非常重要的,实例方法可以返回任何类型的值或者是无返回值(void),而构造方法是没有返回 类型的,void也不行。
3、至于命名就是构造方法与类名相同,当然了实例方法也可以与类名相同,但是习惯上我们为实例方法命名的时 候通常是小写的,另一方面也是与构造方法区分开。
而构造方法与类名相同,所以首字母一般大写。
来源: http://blog.csdn.net/zmissm/article/details/14176725