1.1 java语言有哪些优点?
1.java语言为纯面向对象的语言。
2.平台无关性。java语言的优点便是“一次编译,到处执行”。编译后的程序不会被平台所约束,因此java语言有很好的移植性。
3.java提供了许多内置的类库,将代码封装好来给操作人员使用,从而大大减少开发人员的时间。
4.提供了对web应用的开发的支持。
5.具有较好的安全性和健壮性。
6.去除了c++语言中难以理解,容易混淆的特性,例如头文件,指针,结构,单元运算符重载,虚拟基础类,多重继承等,所以java语言是由c++语言改进并重新设计而来的
1.2 java语言和c/c++有什么异同。
java和C++都是面向对象的语言,都使用了面向对象的思想(例如封装,继承,多态),由于面向对象有许多非常好的特性(继承,组合等),因此二者都有很好的重用性。
下面重点说一下不同点:
1.java为解释型语言,c/c++为编译型语言,java代码由java编译器编译成字节码,然后由JVM解释,C语言代码经过编译和链接生成可执行的二进制代码,因此java的执行速度比c++慢,但是java可跨平台执行,c/c++不能
2.java语言没有指针
3.java只能实现单重继承,但是可以引入多个接口
4.java为纯面向对象语言,所有代码必须在类里实现
5.java语言提供了垃圾回收器来实现对垃圾的自动回收,c++语言中需要开发人员去管理对内存的分配。C语言,通常会把释放资源的代码放在析构函数中,Java没有但是有finalize()方法。
java语言不支持运算符重载,C语言支持
java不支持默认函数参数,c语言支持
java不提供goto语句,c/c++支持,但是在java中goto为保留关键字
java不支持自动强制类型装换,c语言支持
java具有平台无关性,就是对每种数据类型分配固定长度。
java提供对注释文档的内建支持
java包含了一些标准库
1.3 为什么使用public static void main(String[] args)方法?
main是程序的入口方法,所以程序执行时第一个执行的方法就是main方法。
main()方法定义的其他几种格式:
1.static pubic void main(String[] args)
static 和public无先后顺序
2.public static final void main(String[] args)
可以定义为final
3.static public synchronized void main(String[] args)
可以定义为synchronized
不管哪种定义方式,必须保证main()方法类型为void并且有static和public关键字修饰。不可以用abstract关键字,因为main()为程序的入口方法。
1.4静态块
静态块会在类被加载时调用,可以在main()方法前执行
例如:
public class jingtaikuai {
public static void main(String[] args) {
System.out.println("hello word");
}
static{
System.out.println("静态块");
}
}
执行结果:
静态块 hello word
1.5 java程序初始化顺序是怎样的
java程序的初始化一般遵循三个原则(优先级依次递减):
1.静态对象优先于非静态对象
2.父类优先于子类
3.按照成员变量定义顺序进行初始化
常见面试题:
下面代码的运行结果是什么?
class B extends Object{
static {
System.out.println("load b1");
}
public B(){
System.out.println("create b");
}
static{
System.out.println("load b2");
}
}
class A extends B{
static {
System.out.println("load a");
}
public A(){
System.out.println("create a");
}
}
public class 初始化顺序 {
public static void main(String[] args) {
new A();
}
}
执行结果:
load b1 load b2 load a create b create a
1.6 java作用域
在Java语言中,变量的类型主要有3种:成员变量、静态变量和局部变量
首先说静态变量跟局部变量
静态变量不依赖于特定的实例,而是被所有实例共享,也就是说,只要一个类被加载,JVM就会给类的静态变量分配
存储空间。因此可以通过类名.变量名来访问静态变量
局部变量的作用域与可见性为它所在的花括号内
类的成员变量的作用范围同类的实例化对象的作用范围相同。当类被实例化的时候,成员变量就会在内存中分配空间,并初始化。
直到类的实例化对象的生命周期结束时,成员变量的生命周期才结束。
作用域与可见性 | 当前类 | 同一package | 子类 | 其他package |
---|---|---|---|---|
public | √ | √ | √ | √ |
private | √ | × | × | × |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
重点说一下protected和default:
protected:表名成员变量或方法对该类自身,与它在同一个包中的其他类,在其他包中的该类的子类都可见
default:表明该成员变量或方法只有自己和与其位于同一包内的类可见。
若父类与子类处于同一包内,则子类对父类的default成员变量或方法都有访问权限;若父类与子类处于不同的package内,则没有访问权限
还有需要注意的是,这些修饰符只能修饰成员变量,不能修饰局部变量。
private和protected不能用来修饰类
1.7 一个java文件中能否定义多个类
一个java文件中可以定义多个类,但是最多只能有一个类被public修饰,并且这个类的类名必须和文件名相同。
1.8 java的构造函数
一、什么是构造函数
java构造函数,也叫构造方法,是java中一种特殊的函数。函数名与相同,无返回值。
作用:一般用来初始化成员属性和成员方法的,即new对象产生后,就调用了对象了属性和方法。
在现实生活中,很多事物一出现,就天生具有某些属性和行为。比如人一出生,就有年龄、身高、体重、就会哭;汽车一出产,就有颜色、有外观、可以运行等。这些,我们就可以将这些天然的属性和行为定义在构造函数中,当new实例化对象时,也就具有这些属性和方法了,没必要再去重新定义了,从而加快了编程效率。
构造函数是对象一建立就运行,给对象初始化,就包括属性,执行方法中的语句。
而一般函数是对象调用才执行,用".方法名“的方式,给对象添加功能。
一个对象建立,构造函数只运行一次。
而一般函数可以被该对象调用多次。
二、构造函数的特点
1、函数名与类名相同
2、不用定义返回值类型。(不同于void类型返回值,void是没有具体返回值类型;构造函数是连类型都没有)
3、不可以写return语句。(返回值类型都没有,也就不需要return语句了)
注:一般函数不能调用构造函数,只有构造函数才能调用构造函数。
三、示例
1、无参构造函数中只定义了一个方法。new对象时,就调用与之对应的构造函数,执行这个方法。不必写“.方法名”。
package javastudy;
public class ConfunDemo {
public static void main(String[] args) {
Confun c1=new Confun(); //输出Hello World。new对象一建立,就会调用对应的构造函数Confun(),并执行其中的println语句。
}
}
class Confun{
Confun(){ //定义构造函数,输出Hello World
System.out.println("Hellow World");
}
}
输出:Hellow World
2、有参构造函数,在new对象时,将实参值传给private变量,相当于完成setter功能。
package javastudy;
public class ConfunDemo3 {
public static void main(String[] args){
Person z=new Person("zhangsan",3); //实例化对象时,new Person()里直接调用Person构造函数并转转实参,相当于setter功能
z.show();
}
}
class Person{
private String name;
private int age;
public Person(String n,int m){ //有参数构造函数,实现给private成员变量传参数值的功能
name=n;
age=m;
}
//getter //实例化对象时,完成了sett功能后,需要getter,获取实参值。
public String getName(){
return name;
}
public int getAget(){
return age;
}
public void show(){ //获取private值后,并打印输出
System.out.println(name+"
"+age);
}
}
输出: zhangsan 3
以上代码,我们也可以将show()方法中的输出语句直接放在构造函数中,new对象时,即可直接输出值,如下
package javastudy;
public class ConfunDemo3 {
public static void main(String[] args){
Person z=new Person("zhangsan",3); //实例化对象时,new Person()里直接调用Person构造函数并转转实参,同时执行输出语句
}
}
class Person{
private String name;
private int age;
public Person(String n,int m){ //有参数构造函数,实现给private成员变量传参数值的功能,同时直接输出值
name=n;
age=m;
System.out.println(name+"
"+age);
}
}
输出: zhangsan 3
或
class ConFun
{
public static void main(String[] args){
Person z=new Person(20,"zhangsan");
System.out.println(z.getAge()+z.getName());
}
}
class Person
{
private int age;
private String name;
public Person(int x,String y){
age=x;
name=y;
}
public int getAge(){
return age;
}
public String getName(){
return name;
}
}
3、一个对象建立后,构造函数只运行一次。
如果想给对象的值再赋新的值,就要使用set和get方法,此时是当做一般函数使用
如下:
package javastudy;
public class ConfunDemo4 {
public static void main(String[] args) {
PersonDemo s=new PersonDemo("李三",33); //new对象时,即调用对应的构造函数,并传值。同时,不能new同一个对象多次,否则会报错。
s.setName("李五"); //对象建立后,想变更值时,就要用set/get方法,重新设置新的值
s.setName("阿尔法狗"); //并可调用对象多次。
s.print();
}
}
class PersonDemo{
private String name;
private int age;
PersonDemo(String n,int m){ //建立有参构造函数,用于给两个private变量name、age赋值,同时输出值
name=n;
age=m;
System.out.println("姓名:"+name+"年龄:"+age);
}
public void setName(String x){ //set方法,用于再次给name赋值
name=x;
}
public String getName(){ //get方法,用于获取name的赋值
return name;
}
public void print(){
System.out.println(name);
}
}
输出结果:
姓名:李三年龄:33 阿尔法狗
四、默认构造函数
当一个类中没有定义构造函数时,系统会给该类中加一个默认的空参数的构造函数,方便该类初始化。只是该空构造函数是隐藏不见的。
如下,Person(){}这个默认构造函数是隐藏不显示的。
class Person
{
//Person(){}
}
当在该类中自定义了构造函数,默认构造函数就没有了。
如果仍要构造函数,则需要自己在类中手动添加。
五、构造函数的重载
构造函数也是函数的一种,同样具备函数的重载(Overloding)特性。
class Person
{
private String name;
private int age;
Person()
{
System.out.println("A:name="+name+":::age="+age);
}
Person(String n)
{
name = n;
System.out.println("B:name="+name+":::age="+age);
}
Person(String n,int a)
{
name=n;
age=a;
System.out.println("C:name="+name+":::age="+age);
}
}
class PersonDemo2
{
public static void main(String[] args)
{
Person p1=new Person();
Person p2=new Person("lishi");
Person p3=new Person("lishi",10);
}
}
输出结果: A:name=null:::age=0 B:name=lishi:::age=0 C:name=lishi:::age=10
class Person
{
private String name;
private int age;
Person()
{
System.out.println("A:name="+name+":::age="+age);
cry();
}
Person(String n)
{
name = n;
System.out.println("B:name="+name+":::age="+age);
cry();
}
Person(String n,int a)
{
name=n;
age=a;
System.out.println("C:name="+name+":::age="+age);
cry();
}
void cry()
{
System.out.println("Cry...............");
}
}
class PersonDemo2
{
public static void main(String[] args)
{
Person p1=new Person();
Person p2=new Person("lishi");
Person p3=new Person("lishi",10);
}
}
输出结果: A:name=null:::age=0 Cry............... B:name=lishi:::age=0 Cry............... C:name=lishi:::age=10 Cry...............
转自:http://www.cnblogs.com/ibelieve618/p/6364541.html
1.9 java中的clone方法
java中所有的类都继承自Object类,这个类提供了一个clone的方法,这个方法的作用是返回一个Object对象的复制。
使用步骤:
1.继承Cloneable 接口
2.重写clone()方法
3.clone方法中调用super.clone()
4.把浅复制的引用指向原型对象新的克隆体
一、简单用法
只需要在需要clone的对象上实现(implements)Cloneable接口,然后再在类中加上clone方法,在方法中只需要调用super.clone(),根据自己的需要实现即可。
public class Student implements Cloneable {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
输出结果:
testClone.Student@15db9742 age: 1 name: aa testClone.Student@6d06d69c sC.age: 1 sC.name: aa testClone.Student@15db9742 age: 1 name: aa testClone.Student@6d06d69c sC.age: 12 sC.name: bb
分析结果:1、根据输出结果中前边的类名,可以得出被克隆对象的与原来的对象是同一种类型。2、根据内存地址(hashcode)知道,被克隆对象的与原来的对象是存在于内存中的不同的两个对象。所以后边有一个赋值,对原来对象没有任何影响。
二、“影子”克隆与深度克隆
首先看一个例子:
class Bag{//学生的书包
private int width;
private String logo;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
}
public class Student2 implements Cloneable {
private String name;
private int age;
private Bag bag;
public Bag getBag() {
return bag;
}
public void setBag(Bag bag) {
this.bag = bag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}