南京网站建设工作室,宁波外贸网站设计公司,thinkphp做的网站怎么打开,自建营销型网站模板目录1.面向对象和面向过程有什么区别#xff1f;2.面向对象的有哪些特征?3.静态变量和实例变量有什么区别#xff1f;4.Java 对象实例化顺序是怎样的#xff1f;5.浅拷贝和深拷贝的区别是什么#xff1f;5.1.浅拷贝5.2.深拷贝5.3.总结6.Java 中创建对象的方式有哪几种2.面向对象的有哪些特征?3.静态变量和实例变量有什么区别4.Java 对象实例化顺序是怎样的5.浅拷贝和深拷贝的区别是什么5.1.浅拷贝5.2.深拷贝5.3.总结6.Java 中创建对象的方式有哪几种7.重写和重载的区别是什么8.Java 的四种引用方式分别是什么9.构造方法有哪些特点10.抽象类 (abstract class) 和接口 (interface) 有什么共同点和区别11.什么是内部类为什么需要使用内部类12.匿名内部类可以继承类或实现接口吗为什么13.说说内存中的栈 (stack)、堆 (heap) 和静态存储区的用法。1.面向对象和面向过程有什么区别
1面向过程 是分析解决问题的步骤然后用函数把这些步骤一步一步地实现然后在使用的时候一一调用则可。性能较高所以单片机、嵌入式开发等一般采用面向过程开发。 2面向对象 是把构成问题的事务分解成各个对象而建立对象的目的也不是为了完成一个个步骤而是为了描述某个事物在解决整个问题的过程中所发生的行为。面向对象有封装、继承、多态的特征所以易维护、易复用、易扩展可以设计出低耦合的系统。
2.面向对象的有哪些特征?
1抽象 抽象是将一类对象的共同特征总结出来构造类的过程包括数据抽象和行为抽象两方面。抽象只关注对象有哪些属性和行为并不关注这些行为的细节是什么。
2继承 继承是从已有类得到继承信息创建新类的过程。提供继承信息的类被称为父类超类或基类得到继承信息的类被称为子类或派生类。继承让变化中的软件系统有了一定的延续性同时继承也是封装程序中可变因素的重要手段。
3封装 通常认为封装是把数据和操作数据的方法绑定起来对数据的访问只能通过已定义的接口。面向对象的本质就是将现实世界描绘成一系列完全自治、封闭的对象。我们在类中编写的方法就是对实现细节的一种封装我们编写一个类就是对数据和数据操作的封装。可以说封装就是隐藏一切可隐藏的东西只向外界提供最简单的编程接口可以想想普通洗衣机和全自动洗衣机的差别明显全自动洗衣机封装更好因此操作起来更简单我们现在使用的智能手机也是封装得足够好的因为几个按键就搞定了所有的事情。
4多态 多态性是指允许不同子类型的对象对同一消息作出不同的响应。简单地说就是用同样的对象引用调用同样的方法但是做了不同的事情。多态性分为编译时的多态性和运行时的多态性。如果将对象的方法视为对象向外界提供的服务那么运行时的多态性可以解释为当 A 系统访问 B 系统提供的服务时B 系统有多种提供服务的方式但一切对 A 系统来说都是透明的就像电动剃须刀是 A 系统它的供电系统是 B 系统B 系统可以使用电池供电或者用交流电 甚至还有可能是太阳能A 系统只会通过 B 类对象调用供电的方法但并不知道供电系统的底层实现是什么究竟通过何种方式获得了动力。 ① 方法重载overload实现的是编译时的多态性也称为前绑定而方法重写override 实现的是运行时的多态性也称为后绑定。 ② 运行时的多态是面向对象最精髓的东西要实现多态需要做两件事1方法重写。即子类继承父类并重写父类中已 有的或抽象的方法2对象造型用父类型引用引用子类型对象这样同样的引用调用同样的方法就会根据子类对象的不同而表现出不同的行为。
3.静态变量和实例变量有什么区别
1静态变量是被 static 修饰符修饰的变量也称为类变量它属于类不属于类的任何一个对象一个类不管创建多少个对象静态变量在内存中有且仅有一份。静态变量可以实现让多个对象共享内存。在 Java 开发中上下文类和工具类中通常会有大量的静态成员。 2实例变量必须依存于某一实例需要先创建对象然后通过对象才能访问到它。
4.Java 对象实例化顺序是怎样的
1类加载器实例化时进行的操作步骤加载 - 连接 - 初始化。
2实例化优先级顺序父类 子类 静态代码块 非静态代码块 构造函数具体按照如下顺序 ① 按照代码书写顺序加载父类静态变量和父类静态代码块 ② 按照代码书写顺序加载子类静态变量和子类静态代码块 ③ 父类非静态变量父类实例成员变量 ④ 父类非静态代码块 ⑤ 父类构造函数 ⑥ 子类非静态变量子类实例成员变量 ⑦ 子类非静态代码块 ⑧ 子类构造函数
3举例说明如下
class A {//静态代码块只初始化一次static {System.out.println(父类的静态代码块...);}//非静态代码块{System.out.println(父类的非静态代码块...);}//构造函数public A() {System.out.println(父类的构造函数...);}
}class B extends A {//静态代码块只初始化一次static {System.out.println(子类的静态代码块...);}//非静态代码块{System.out.println(子类的非静态代码块...);}//构造函数public B() {System.out.println(子类的构造函数...);}
}public class Solution {public static void main(String[] args) {A ab new B();System.out.println(---------);ab new B();}
}上述代码的输出结果如下
父类的静态代码块...
子类的静态代码块...
父类的非静态代码块...
父类的构造函数...
子类的非静态代码块...
子类的构造函数...
------------
父类的非静态代码块...
父类的构造函数...
子类的非静态代码块...
子类的构造函数...5.浅拷贝和深拷贝的区别是什么
5.1.浅拷贝
浅拷贝是创建一个新对象该对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型拷贝的就是基本类型的值如果属性是引用类型那么拷贝的就是内存地址 。
public class Address {int id;String addressName;public int getId() {return id;}public String getAddressName() {return addressName;}public Address(int id, String addressName) {this.id id;this.addressName addressName;}public void setId(int id) {this.id id;}public void setAddressName(String addressName) {this.addressName addressName;}Overridepublic String toString() {return Address{ id id , addressName addressName \ };}
}public class Person implements Cloneable {private int id;private String name;private Address address;public String getName() {return name;}public void setId(int id) {this.id id;}public void setName(String name) {this.name name;}public int getId() {return id;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address address;}public Person(int id, String name, Address address) {this.id id;this.name name;this.address address;}Overrideprotected Object clone() throws CloneNotSupportedException {return (Person) super.clone();}Overridepublic String toString() {return Person{ id id , name name \ , address address };}
}public class Test {public static void main(String[] args) throws CloneNotSupportedException {Person person1 new Person(1, 小华, new Address(1, 北京));//浅拷贝Person person2 (Person) person1.clone();System.out.println(person1 person2 的结果为 (person1 person2));System.out.println(\n改变person1的属性值之前);System.out.println(person1: person1);System.out.println(person2: person2);System.out.println(person1.getName() person2.getName()的结果为 (person1.getName() person2.getName()));System.out.println(person1.getAddress() person2.getAddress()的结果为 (person1.getAddress() person2.getAddress()));person1.setId(2);person1.setName(小明);person1.getAddress().setId(2);person1.getAddress().setAddressName(武汉);System.out.println(\n改变person1的属性值之后);System.out.println(person1: person1);System.out.println(person2: person2);System.out.println(person1.getName() person2.getName()的结果为 (person1.getName() person2.getName()));System.out.println(person1.getAddress() person2.getAddress()的结果为 (person1.getAddress() person2.getAddress()));}
}5.2.深拷贝
1深拷贝是将一个对象从内存中完整的拷贝一份出来即从堆内存中开辟一个新的区域存放新对象。新对象与原对象不共享内存修改新对象也不会影响原对象。
2实现方式如下 ① 通过对象序列化实现深拷贝推荐 先将 Address 类和 Person 类实现 Serializable 接口然后再修改Test.java中的代码即可。
public class Test {public static void main(String[] args) throws Exception {Person person1 new Person(1,小华,new Address(1,北京));//创建对象输出流对象ObjectOutputStream oos new ObjectOutputStream(new FileOutputStream(E:\\testData\\a.txt));//写对象oos.writeObject(person1);//释放资源oos.close();//创建对象输入流对象ObjectInputStream ois new ObjectInputStream(new FileInputStream(E:\\testData\\a.txt));//读取对象深拷贝Person person2 (Person) ois.readObject();//释放资源ois.close();System.out.println(person1 person2 的结果为 (person1 person2));System.out.println(\n改变person1的属性值之前);System.out.println(person1: person1);System.out.println(person2: person2);System.out.println(person1.getName() person2.getName()的结果为 (person1.getName() person2.getName()));System.out.println(person1.getAddress() person2.getAddress()的结果为 (person1.getAddress() person2.getAddress()));person1.setId(2);person1.setName(小明);person1.getAddress().setId(2);person1.getAddress().setAddressName(武汉);System.out.println(\n改变person1的属性值之后);System.out.println(person1: person1);System.out.println(person2: person2);System.out.println(person1.getName() person2.getName()的结果为 (person1.getName() person2.getName()));System.out.println(person1.getAddress() person2.getAddress()的结果为 (person1.getAddress() person2.getAddress()));}
}② 重写Person 类中的 clone() 方法来实现深拷贝
public class Address implements Cloneable {//...Overridepublic Object clone() throws CloneNotSupportedException {return (Address) super.clone();}//...
}public class Person implements Cloneable {//...Overridepublic Object clone() throws CloneNotSupportedException {Person person null;person (Person)super.clone();//对引用数据类型单独处理person.name new String(name);person.address (Address)address.clone();return person;}//...
}5.3.总结
操作是否指向同一个堆内存地址基本数据类型引用数据类型赋值是会改变会改变浅拷贝否不会改变会改变深拷贝否不会改变不会改变
6.Java 中创建对象的方式有哪几种
1使用 new 关键字 这是最常见也是最简单的创建对象的方式通过这种方式我们可以调用任意的构造函数无参的和有参的。
public class Student {public static void main(String[] args) {Student student new Student();}
}2通过反射机制 ① 使用 Class 类中的 newInstance 方法 使用 Class 类中的 newInstance 方法创建对象。这个 newInstance 方法调用无参的构造函数创建对象。
public class Student {public static void main(String[] args) throws Exception {//使用 Class 类中的 newInstance 方法创建对象有以下两种方式Student student1 (Student) Class.forName(test.Student).newInstance();Student student2 Student.class.newInstance();System.out.println(student1 student2); //false}
}② Constructor 类中的 newInstance 方法 和 Class 类中的 newInstance 方法很像 java.lang.reflect.Constructor 类里也有一个 newInstance 方法可以创建对象。我们可以通过这个newInstance 方法调用有参数的和私有的构造函数。
public class Student {public static void main(String[] args) throws Exception {ConstructorStudent constructor Student.class.getConstructor();Student student constructor.newInstance();}
}3使用 clone 方法 无论何时我们调用一个对象的 clone()JVM 就会创建一个新的对象将前面对象的内容全部拷贝进去。用 clone() 创建对象并不会调用任何构造函数。要使用 clone()我们需要先实现 Cloneable 接口并实现其定义的 clone()。
public class Student implements Cloneable {Overrideprotected Object clone() throws CloneNotSupportedException {System.out.println(具体原型复制成功);return (Student)super.clone();}public static void main(String[] args) throws CloneNotSupportedException {Student student1 new Student();Student student2 (Student)student1.clone();System.out.println(student1 student2); //false}
}4通过序列化机制 ① 序列化就是把对象通过流的方式存储到文件中此对象要重写 Serializable 接口才能被序列化。 ② 反序列化就是把文件中的内容读取出来还原为 Java 对象该过程也需要实现 Serializable 接口。 当我们序列化和反序列化一个对象JVM 会给我们创建一个单独的对象。在反序列化时JVM 创建对象并不会调用任何构造函数。
public class Student implements Serializable {private int age;public int getAge() {return age;}public void setAge(int age) {this.age age;}public static void main(String[] args) throws Exception {ObjectOutputStream out new ObjectOutputStream(new FileOutputStream(stu.txt));Student student1 new Student();student1.setAge(18);out.writeObject(student1);ObjectInputStream in new ObjectInputStream(new FileInputStream(stu.txt));Student student2 (Student) in.readObject();System.out.println(student2.getAge()); //18System.out.println(student1 student2); //false}
}7.重写和重载的区别是什么
1重写 (Override) 从字面上看重写就是重新写一遍的意思。其实就是在子类中把父类本身有的方法重新写一遍。子类继承了父类原有的方法但有时子类并不想原封不动的继承父类中的某个方法 此时可以对方法体进行修改或重写。但需要注意以下几点简称两同两小加一大原则 ① 方法名、参数列表相同 ② 子类返回类型小于等于父类方法返回类型、重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常 ③ 子类函数的访问修饰权限要大于等于父类的 (public protected default private)
public class Father {public void sayHello() {System.out.println(Hello, Father); //Hello, Son}public static void main(String[] args) {Son s new Son();s.sayHello();}
}class Son extends Father{Overridepublic void sayHello() {// TODO Auto-generated method stubSystem.out.println(Hello, Son);}
}2重载 (Overload) 在一个类中同名的方法如果有不同的参数列表参数类型不同、参数个数不同甚至是参数顺序不同则视为重载它是一个类中多态性的一种表现。同时重载对返回类型没有要求可以相同也可以不同但不能通过返回类型是否相同来判断重载。
public class Father {public static void main(String[] args) {// TODO Auto-generated method stubFather s new Father();s.sayHello();s.sayHello(wintershii);}public void sayHello() {System.out.println(Hello);}public void sayHello(String name) {System.out.println(Hello name);}
}8.Java 的四种引用方式分别是什么
1强引用 (Strong Reference) 强引用是平常中使用最多的引用在程序内存不足时也不会被垃圾收集器回收。
//使用方式
Object objnew Object()2软引用 (Soft Reference) ① 软引用在程序内存不足时会被回收。 ② 可用场景 创建缓存的时候创建的对象放进缓存中当内存不足时JVM 就会回收早先创建的对象。
/*注意wrf 这个引用也是强引用它是指向 SoftReference 这个对象的这里的软引用指的是指向new String(str)的引用也就是 SoftReference 类中T
*/
SoftReferenceString wrf new SoftReferenceString(new String(str));3弱引用 (Weak Reference) ① 弱引用就是只要 JVM 垃圾回收器发现了它就会将其回收。 ② 可用场景 Java 源码中 java.util.WeakHashMap 中的 key 就是使用弱引用一旦我不需要某个引用JVM 会自动帮忙处理它这样我们就不需要做其它操作。
//使用方式
WeakReferenceString wrf new WeakReferenceString(str);4虚引用 (Phantom Reference) ① 虚引用的回收机制跟弱引用差不多但是它被回收之前会被放入 ReferenceQueue 中。需要注意的是其它引用是被 JVM 回收后才被传入 ReferenceQueue 中的。由于这个机制所以虚引用大多被用于引用销毁前的处理工作。此外虚引用创建的时候必须带有ReferenceQueue。 ② 可用场景 对象销毁前的一些操作比如说资源释放等。 Object.finalize() 虽然也可以做这类动作但是这个方式即不安全又低效。
//使用方式
PhantomReferenceString prf new PhantomReferenceString(new String(str), new ReferenceQueue());注意上诉所说的几类引用都是指对象本身的引用而不是指 Reference 的四个子类的引用。
9.构造方法有哪些特点
1名字必须与类名相同。 2没有返回值也不能用 void 声明构造函数。 3生成类的对象时自动调用且在整个对象的生命周期内只调用一次。 4构造方法不能被 override重写但是可以 overload重载所以我们经常可以看到一个类中有多个构造方法的情况。 5如果用户没有显式定义构造方法编译器就会默认生成一份构造方法而且默认生成的构造方法一定是无参的。不过一旦用户定义了一个构造方法编译器咋不会自动生成的构造方法。
10.抽象类 (abstract class) 和接口 (interface) 有什么共同点和区别
1共同点
都不能被实例化都可以包含抽象方法都可以有默认实现的方法JDK 1.8 可以用 default 关键字在接口中定义默认方法
2区别
基本使用 抽象类只能继承一个接口可以实现多个即单继承多实现接口比抽象类更加抽象因为抽象类中可以定义构造方法可以有抽象方法和具体方法。而接口中不能定义构造方法而且其中的方法全部都是抽象方法默认且只能是 public abstract 的 抽象类中可以定义静态块而接口中则不能抽象类中可以定义成员变量并且接口中定义的成员变量实际上都是常量默认且只能是 public static final 的 有抽象方法的类必须被声明为抽象类而抽象类未必要有抽象方法 设计目的 接口的设计目的是对类的行为进行约束更准确的说是一种有约束因为接口不能规定类不可以有什么行为也就是提供一种机制可以强制要求不同的类具有相同的行为。它只约束了行为的有无但不对如何实现行为进行限制。抽象类的设计目的是代码复用。当不同的类具有某些相同的行为记为行为集合 A且其中一部分行为的实现方式一致时A的非真子集记为B可以让这些类都派生于一个抽象类。在这个抽象类中实现了 B避免让所有的子类来实现 B这就达到了代码复用的目的。而 A - B 的部分留给各个子类自己实现。正是因为 A - B 在这里没有实现所以抽象类不允许实例化出来否则当调用到 A - B 时无法执行)。 设计思想 抽象类是对类本质的抽象自下而上表达的是 is xxx 的关系比如: BMW is a car。抽象类包含并实现子类的通用特性将子类存在差异化的特性进行抽象交由子类去实现。而接口是对行为的抽象自上而下表达的是 like xxx 的关系。比如Bird like a Aircraft像飞行器一样可以飞但其本质上 is a Bird。接口的核心是定义行为即实现类可以做什么至于实现类主体是谁、是如何实现的接口并不关心。 使用场景当关注事物的本质时使用抽象类当关注事物的操作时使用接口。复杂度抽象类的功能要远超过接口但是定义抽象类的代价比较高。因为对于Java来说每个类只能继承一个类在这个类中你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口在设计阶段会降低难度。
11.什么是内部类为什么需要使用内部类
1简单来说内部类 (inner class) 是定义在另一个类中的类。
2使用内部类的主要原因有以下三点 ① 内部类方法可以访问该类定义所在的作用域中的数据包括私有的数据。 ② 内部类可以对同一个包中的其他类隐藏起来。 ③ 当想要定义一个回调函数且不想编写大量代码时使用匿名 (anonymous) 内部类比较便捷。
12.匿名内部类可以继承类或实现接口吗为什么
1匿名内部类本质上是对父类方法的重写或对接口方法的实现。从语法角度看匿名内部类创建处无法使用关键字继承类或实现接口。
2原因如下 ① 匿名内部类没有名字所以它没有构造函数。因为没有构造函数所以它必须通过父类的构造函数来实例化。即匿名内部类完全把创建对象的任务交给了父类去完成。 ② 匿名内部类里创建新的方法没有太大意义新方法无法被调用。 ③ 匿名内部类一般是用来覆盖父类的方法。 ④ 匿名内部类没有名字所以无法进行向下的强制类型转换只能持有匿名内部类对象引用的变量类型的直接或间接父类。
13.说说内存中的栈 (stack)、堆 (heap) 和静态存储区的用法。
1通常我们定义一个基本数据类型的变量一个对象的引用还有就是函数调用的现场保存都使用内存中的栈空间 2通过 new 关键字和构造器创建的对象放在堆空间 3程序中的字面量 (literal) 如直接书写的 100、“hello, world” 和常量都是放在静态存储区中。 4栈空间操作最快但是也很小通常大量的对象都是放在堆空间整个内存包括硬盘上的虚拟内存都可以被当成堆空间来使用。 5String str new String(“hello”); 上面的语句中 str 放在栈中用 new 创建出来的字符串对象放在堆中而 “hello” 这个字面量放在静态存储区一共创建了两个字符串对象。