Java编程面试前50名问题

介绍

如果你在面试Java编程角色,那么你的编码技能可能会受到测试。无论你是Java的初学者还是专业程序员,本文提供了一些常见的Java面试问题和答案,以帮助你做好准备。

1. 如何在Java中反转字符串?

String类中没有reverse()实用方法。但是,你可以从字符串创建一个字符数组,然后从末尾向开头迭代它。你可以将字符追加到一个字符串构建器,最后返回反转后的字符串。

以下示例代码展示了一种反转字符串的方法:

public class StringPrograms {

	public static void main(String[] args) {
		String str = "123";

		System.out.println(reverse(str));
	}

	public static String reverse(String in) {
		if (in == null)
			throw new IllegalArgumentException("Null is not valid input");

		StringBuilder out = new StringBuilder();

		char[] chars = in.toCharArray();

		for (int i = chars.length - 1; i >= 0; i--)
			out.append(chars[i]);

		return out.toString();
	}

}

在方法中添加null检查并使用StringBuilder追加字符会获得额外的奖励分。注意,在Java中索引从0开始,所以在for循环中需要从chars.length - 1开始。

2. 如何在Java中不使用第三个变量交换两个数字?

在不使用第三个变量的情况下交换数字是一个三步过程,在代码中更容易理解:

b = b + a; // now b is sum of both the numbers
a = b - a; // b - a = (b + a) - a = b (a is swapped)
b = b - a; // (b + a) - b = a (b is swapped)

以下示例代码展示了一种实现数字交换方法的方式:

public class SwapNumbers {

public static void main(String[] args) {
	int a = 10;
	int b = 20;

    System.out.println("a is " + a + " and b is " + b);

	a = a + b;
	b = a - b;
	a = a - b;

    System.out.println("After swapping, a is " + a + " and b is " + b);
    }

}

输出显示整数值已经交换:

Output
a is 10 and b is 20 After swapping, a is 20 and b is 10

3. 编写一个Java程序来检查字符串中是否存在元音字母。

以下示例代码展示了如何使用正则表达式来检查字符串是否包含元音字母:

public class StringContainsVowels {

	public static void main(String[] args) {
		System.out.println(stringContainsVowels("Hello")); // true
		System.out.println(stringContainsVowels("TV")); // false
	}

	public static boolean stringContainsVowels(String input) {
		return input.toLowerCase().matches(".*[aeiou].*");
	}

}

4. 编写一个Java程序来检查给定的数字是否为素数。

您可以编写一个程序来将给定的数字n除以从2到n/2的数字,并检查余数。如果余数为0,则它不是素数。以下示例代码展示了一种检查给定数字是否为素数的方法:

public class PrimeNumberCheck {

	public static void main(String[] args) {
		System.out.println(isPrime(19)); // true
		System.out.println(isPrime(49)); // false
	}

	public static boolean isPrime(int n) {
		if (n == 0 || n == 1) {
			return false;
		}
		if (n == 2) {
			return true;
		}
		for (int i = 2; i <= n / 2; i++) {
			if (n % i == 0) {
				return false;
			}
		}

		return true;
	}

}

虽然这个程序能够工作,但它不够内存和时间高效。考虑到,对于给定的数字N,如果存在一个素数M介于2√N(N的平方根)之间,可以整除它,那么N就不是一个素数。

5. 编写一个Java程序,使用递归打印斐波那契数列。

A Fibonacci sequence is one in which each number is the sum of the two previous numbers. In this example, the sequence begins with 0 and 1. The following example code shows how to use a for loop to print a Fibonacci sequence:

public class PrintFibonacci {

	public static void printFibonacciSequence(int count) {
		int a = 0;
		int b = 1;
		int c = 1;

		for (int i = 1; i <= count; i++) {
			System.out.print(a + ", ");

            a = b;
			b = c;
			c = a + b;
		}
	}

	public static void main(String[] args) {
    	printFibonacciSequence(10);
	}

}
Output
0, 1, 1, 2, 3, 5, 8, 13, 21, 34,

您也可以使用递归来打印斐波那契数列,因为斐波那契数是通过在序列中添加前两个数字来生成的:

F(N) = F(N-1) + F(N-2)

以下示例类展示了如何使用递归来计算一个长度为10的斐波那契数列:

public class PrintFibonacciRecursive {

    public static int fibonacci(int count) {
		if (count <= 1)
			return count;

		return fibonacci(count - 1) + fibonacci(count - 2);
	}

	public static void main(String args[]) {
    	int seqLength = 10;

    	System.out.print("A Fibonacci sequence of " + seqLength + " numbers: ");

    	for (int i = 0; i < seqLength; i++) {
      	    System.out.print(fibonacci(i) + " ");
    	}
  	}

}
Output
A Fibonacci sequence of 10 numbers: 0 1 1 2 3 5 8 13 21 34

6. 如何在Java中检查整数列表是否仅包含奇数?

您可以使用for循环检查每个元素是否为奇数:

public static boolean onlyOddNumbers(List<Integer> list) {
	for (int i : list) {
		if (i % 2 == 0)
			return false;
	}

	return true;
}

如果列表很大,可以使用并行流进行更快的处理,如以下示例代码所示:

public static boolean onlyOddNumbers(List<Integer> list) {
	return list
			.parallelStream() // 用于更快处理的并行流
			.anyMatch(x -> x % 2 != 0); // 一旦有元素匹配条件就立即返回
}

要了解确定整数是否为奇数背后的数学原理,请参阅维基百科上的模运算

7. 如何检查一个字符串是否是Java中的回文?

A palindrome string is the same string backwards or forwards. To check for a palindrome, you can reverse the input string and check if the result is equal to the input. The following example code shows how to use the String charAt(int index) method to check for palindrome strings:

boolean checkPalindromeString(String input) {
	boolean result = true;
	int length = input.length();

	for (int i = 0; i < length/2; i++) {
		if (input.charAt(i) != input.charAt(length - i - 1)) {
			result = false;
			break;
		}
	}

	return result;
}

8. 如何在Java中从字符串中删除空格?

以下示例代码展示了使用Character.isWhitespace()方法从字符串中移除空格的一种方法:

String removeWhiteSpaces(String input) {
	StringBuilder output = new StringBuilder();
	
	char[] charArray = input.toCharArray();
	
	for (char c : charArray) {
		if (!Character.isWhitespace(c))
			output.append(c);
	}
	
	return output.toString();
}

了解更多关于在Java中从字符串中移除空格和其他字符的信息

9. 如何在Java中移除字符串的前导和尾随空格?

String类包含两个方法来移除前导和尾随空白:trim()strip()strip()方法是在Java 11中添加到String类的。 strip()方法使用Character.isWhitespace()方法来检查字符是否为空格。此方法使用Unicode码点,而trim()方法将代码点值小于或等于U+0020的任何字符视为空格字符。

strip()方法是推荐的去除空格的方法,因为它使用了Unicode标准。以下示例代码展示了如何使用strip()方法去除空格:

String s = "  abc  def\t";
		
s = s.strip();
		
System.out.println(s);

因为String是不可变的,所以您必须将strip()的输出分配给字符串。

10. 如何在Java中对数组进行排序?

Arrays实用程序类有许多重载的sort()方法,用于对基本类型和对象数组进行排序。如果要按自然顺序对基本类型数组进行排序,则可以使用Arrays.sort()方法,如下例所示:

int[] array = {1, 2, 3, -1, -2, 4};

Arrays.sort(array);

System.out.println(Arrays.toString(array));

但是,如果要对对象数组进行排序,则该对象必须实现Comparable接口。如果要指定排序标准,则可以传递Comparator以进行排序逻辑。了解有关Java中Comparable和Comparator的更多信息。

11. 如何在Java中通过编程方式创建死锁场景?

死锁是多线程Java环境中的一种情况,其中两个或多个线程被永久阻塞。死锁情况发生在两个或多个线程时。以下示例代码创建了一个死锁场景:

public class ThreadDeadlock {

    public static void main(String[] args) throws InterruptedException {
        Object obj1 = new Object();
        Object obj2 = new Object();
        Object obj3 = new Object();
    
        Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1");
        Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2");
        Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3");
        
        t1.start();
        Thread.sleep(5000);
        t2.start();
        Thread.sleep(5000);
        t3.start();        
    }

}

class SyncThread implements Runnable {

    private Object obj1;
    private Object obj2;

    public SyncThread(Object o1, Object o2) {
        this.obj1 = o1;
        this.obj2 = o2;
    }

    @Override
    public void run() {
        String name = Thread.currentThread().getName();

        System.out.println(name + " acquiring lock on " + obj1);
        synchronized (obj1) {
            System.out.println(name + " acquired lock on " + obj1);
            work();
            System.out.println(name + " acquiring lock on " + obj2);
            synchronized (obj2) {
                System.out.println(name + " acquired lock on " + obj2);
                work();
            }
            System.out.println(name + " released lock on " + obj2);
        }
        System.out.println(name + " released lock on " + obj1);
        System.out.println(name + " finished execution.");
    }

    private void work() {
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

所有三个线程都能获取第一个对象的锁。然而,它们正在使用共享资源,并以一种导致它们无限等待获取第二个对象锁的方式启动。您可以使用Java线程转储来检测死锁。了解更多关于Java中死锁的信息。

12. 如何在Java中找到整数的阶乘?

整数的阶乘是通过将从1到给定数字的所有数字相乘来计算的:

F(n) = F(1)*F(2)...F(n-1)*F(n)

以下示例代码显示了如何使用递归来找到整数的阶乘:

public static long factorial(long n) {
	if (n == 1)
		return 1;
	else
		return (n * factorial(n - 1));
}

13. 如何在Java中反转链表?

LinkedList descendingIterator() 返回一个迭代器,该迭代器以相反的顺序迭代元素。以下示例代码显示了如何使用此迭代器创建一个新的链表,其中元素按照相反的顺序列出:

LinkedList<Integer> ll = new LinkedList<>();

ll.add(1);
ll.add(2);
ll.add(3);

System.out.println(ll);

LinkedList<Integer> ll1 = new LinkedList<>();

ll.descendingIterator().forEachRemaining(ll1::add);

System.out.println(ll1);

了解如何从数据结构和算法的角度来反转链表

14. 如何在Java中实现二分查找?

要实现二分查找,数组元素必须是排序的。二分查找算法基于以下条件:

  • 如果关键字小于中间元素,则现在只需在数组的前半部分进行搜索。
  • 如果关键字大于中间元素,则需要在数组的后半部分进行搜索。
  • 如果关键字等于数组中间的元素,则搜索结束。
  • 最后,如果整个数组中未找到关键字,则应返回-1。这表示元素不存在。

以下示例代码实现了二分查找:

public static int binarySearch(int arr[], int low, int high, int key) {
	int mid = (low + high) / 2;

	while (low <= high) {
		if (arr[mid] < key) {
			low = mid + 1;
		} else if (arr[mid] == key) {
			return mid;
		} else {
			high = mid - 1;
		}
		mid = (low + high) / 2;
	}

	if (low > high) {
		return -1;
	}

	return -1;
}

15. 编写一个Java程序来说明归并排序。

归并排序是最有效率的排序算法之一。它基于“分而治之”的原则。其核心思想是将一个列表拆分成多个子列表,直到每个子列表只包含一个元素,然后以一种合并这些子列表的方式形成一个排序列表。以下示例代码展示了使用归并排序的一种方式:

public class MergeSort {

	public static void main(String[] args) {
		int[] arr = { 70, 50, 30, 10, 20, 40, 60 };

		int[] merged = mergeSort(arr, 0, arr.length - 1);

		for (int val : merged) {
			System.out.print(val + " ");
		}
	}

	public static int[] mergeTwoSortedArrays(int[] one, int[] two) {
		int[] sorted = new int[one.length + two.length];

		int i = 0;
		int j = 0;
		int k = 0;

		while (i < one.length && j < two.length) {
			if (one[i] < two[j]) {
				sorted[k] = one[i];
				k++;
				i++;
			} else {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (i == one.length) {
			while (j < two.length) {
				sorted[k] = two[j];
				k++;
				j++;
			}
		}

		if (j == two.length) {
			while (i < one.length) {
				sorted[k] = one[i];
				k++;
				i++;
			}
		}

		return sorted;
	}

	public static int[] mergeSort(int[] arr, int lo, int hi) {
		if (lo == hi) {
			int[] br = new int[1];
			br[0] = arr[lo];

			return br;
		}

		int mid = (lo + hi) / 2;

		int[] fh = mergeSort(arr, lo, mid);
		int[] sh = mergeSort(arr, mid + 1, hi);

		int[] merged = mergeTwoSortedArrays(fh, sh);

		return merged;
	}

}

16. 你能在Java中创建字符金字塔吗?

模式程序是面试中非常流行的话题。这种类型的问题用于了解面试者的逻辑思维能力。请参考Java中的金字塔模式程序,以获取创建不同类型金字塔模式的示例。

17. 编写一个Java程序,检查两个数组是否包含相同的元素。

检查两个数组是否包含相同的元素,首先需要从这两个数组中创建一个元素集,并比较这些集合中的元素,以查找是否存在一个元素不在两个集合中都存在。以下示例代码显示了如何检查两个数组是否仅包含相同元素:

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class ArraySameElements {

	public static void main(String[] args) {
		Integer[] a1 = {1,2,3,2,1};
		Integer[] a2 = {1,2,3};
		Integer[] a3 = {1,2,3,4};
		
		System.out.println(sameElements(a1, a2));
		System.out.println(sameElements(a1, a3));
	}

	static boolean sameElements(Object[] array1, Object[] array2) {
		Set<Object> uniqueElements1 = new HashSet<>(Arrays.asList(array1));
		Set<Object> uniqueElements2 = new HashSet<>(Arrays.asList(array2));
		
		// 如果大小不同,意味着存在不匹配
		if (uniqueElements1.size() != uniqueElements2.size()) return false;
		
		for (Object obj : uniqueElements1) {
			// 两者中均不存在的元素?
			if (!uniqueElements2.contains(obj)) return false;
		}
		
		return true;
	}

}
Output
true false

18. 如何在Java中获取整数数组中所有元素的总和?

您可以使用for循环遍历数组元素并将它们相加以获取最终总和:

int[] array = { 1, 2, 3, 4, 5 };

int sum = 0;

for (int i : array)
	sum += i;

System.out.println(sum);

19. 如何在Java数组中找到第二大的数字?

解决这个问题有许多方法。您可以对数组进行自然升序排序并取第二个最后的值。但是,排序是一项昂贵的操作。您还可以使用两个变量在单次迭代中找到第二大的值,如以下示例所示:

private static int findSecondHighest(int[] array) {
	int highest = Integer.MIN_VALUE;
	int secondHighest = Integer.MIN_VALUE;

	for (int i : array) {
		if (i > highest) {
			secondHighest = highest;
			highest = i;
		} else if (i > secondHighest) {
			secondHighest = i;
		}

	}
	return secondHighest;
}

20. 如何在Java中对数组进行洗牌?

以下示例代码演示了如何使用Random类生成随机索引号并对元素进行洗牌:

int[] array = { 1, 2, 3, 4, 5, 6, 7 };

Random rand = new Random();

for (int i = 0; i < array.length; i++) {
	int randomIndexToSwap = rand.nextInt(array.length);
	int temp = array[randomIndexToSwap];
	array[randomIndexToSwap] = array[i];
	array[i] = temp;
}

System.out.println(Arrays.toString(array));

您可以在另一个for循环中运行洗牌代码以进行多轮洗牌。

21. 如何在Java中查找文本文件中的字符串?

以下示例代码演示了如何使用Scanner类逐行读取文件内容,然后使用String contains()方法检查字符串是否存在于文件中:

boolean findStringInFile(String filePath, String str) throws FileNotFoundException {
	File file = new File(filePath);

	Scanner scanner = new Scanner(file);

	// 逐行读取文件
	while (scanner.hasNextLine()) {
		String line = scanner.nextLine();
		if (line.contains(str)) {
			scanner.close();
			return true;
		}
	}
	scanner.close();

	return false;
}

请注意,示例代码假定要在文件中搜索的字符串不包含换行符。

22. 如何在Java中以特定格式打印日期?

以下是一个示例代码,演示如何使用SimpleDateFormat类格式化日期字符串:

String pattern = "MM-dd-yyyy";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);

String date = simpleDateFormat.format(new Date());
System.out.println(date); // 2020-06-23

了解更多关于Java SimpleDateFormat的信息。

23. 如何在Java中合并两个列表?

以下是一个示例代码,演示如何使用addAll()方法在Java中合并多个列表:

List<String> list1 = new ArrayList<>();
list1.add("1");
List<String> list2 = new ArrayList<>();
list2.add("2");

List<String> mergedList = new ArrayList<>(list1);
mergedList.addAll(list2);
System.out.println(mergedList); // [1, 2]

24. 编写一个Java程序,按值对HashMap进行排序。

HashMap不是有序集合。以下示例代码演示如何根据值对条目进行排序,并将它们存储到LinkedHashMap中,该集合保持插入顺序:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class SortHashMapByValue {

	public static void main(String[] args) {
		Map<String, Integer> scores = new HashMap<>();

		scores.put("David", 95);
		scores.put("Jane", 80);
		scores.put("Mary", 97);
		scores.put("Lisa", 78);
		scores.put("Dino", 65);

		System.out.println(scores);

		scores = sortByValue(scores);

		System.out.println(scores);
	}

	private static Map<String, Integer> sortByValue(Map<String, Integer> scores) {
		Map<String, Integer> sortedByValue = new LinkedHashMap<>();

		// 获取条目集合
		Set<Entry<String, Integer>> entrySet = scores.entrySet();
		System.out.println(entrySet);

		// 由于集合是无序的,创建一个列表
		List<Entry<String, Integer>> entryList = new ArrayList<>(entrySet);
		System.out.println(entryList);

		// 按值对列表进行排序
		entryList.sort((x, y) -> x.getValue().compareTo(y.getValue()));
		System.out.println(entryList);

		// 填充新的哈希映射
		for (Entry<String, Integer> e : entryList)
			sortedByValue.put(e.getKey(), e.getValue());

		return sortedByValue;
	}

}

25. 如何在Java中从输入字符串中移除所有给定字符的出现?

String类没有移除字符的方法。以下示例代码演示如何使用replace()方法创建一个没有给定字符的新字符串:

String str1 = "abcdABCDabcdABCD";
		
str1 = str1.replace("a", ""); 

System.out.println(str1); // bcdABCDbcdABCD

在Java中,字符串是不可变的。所有字符串操作方法都会返回一个新字符串,这就是为什么你需要将它赋值给另一个变量的原因。了解更多关于在Java中从字符串中移除字符的信息。

26. 如何在Java中获取字符串中不同字符及其出现次数?

您可以从字符串创建字符数组。然后遍历数组,使用字符作为键,它们的出现次数作为值创建一个HashMap。以下示例代码展示了如何提取并统计字符串中的字符:

String str1 = "abcdABCDabcd";

char[] chars = str1.toCharArray();

Map<Character, Integer> charsCount = new HashMap<>();

for (char c : chars) {
	if (charsCount.containsKey(c)) {
		charsCount.put(c, charsCount.get(c) + 1);
	} else
		charsCount.put(c, 1);
}

System.out.println(charsCount); // {a=2, A=1, b=2, B=1, c=2, C=1, d=2, D=1}

27. 你能证明Java中的String对象在程序上是不可变的吗?

以下示例代码演示了如何证明String对象是不可变的,代码中的注释解释了每个步骤:

String s1 = "Java"; // "Java" 字符串在池中创建,并分配引用给 s1

String s2 = s1; // s2 也有相同的引用指向池中的 "Java"

System.out.println(s1 == s2); // 证明 s1 和 s2 具有相同的引用

s1 = "Python"; 
// 上面改变了 s1 的值,所以字符串是不可变的吗?

// 在上面的情况下,一个新的字符串 "Python" 在池中创建了
// 现在 s1 指向池中的新字符串
// 但是,原始字符串 "Java" 仍然未更改,并保留在池中
// s2 仍然指向池中的原始字符串 "Java"

// 证明 s1 和 s2 具有不同的引用
System.out.println(s1 == s2); 

System.out.println(s2); 
// 打印 "Java",支持原始字符串值未更改的事实,因此字符串是不可变的

28. 你能写一些展示 Java 中继承的代码吗?

以下是一个示例代码,演示了如何使用extends关键字创建Animal类的子类。新类Cat继承了Animal类的变量,并添加了仅属于Cat类的其他代码。

class Animal {
	String color;
}

class Cat extends Animal {
	void meow() {
		System.out.println("Meow");
	}
}

29. 如何在Java中展示具有多重继承的菱形问题?

菱形问题发生在一个类从多个类继承并且在不清楚从哪个类执行哪个方法时发生模糊。为避免菱形问题,Java不允许继承多个类,如以下示例所示:

interface I {
	void foo();
}
class A implements I {
	public void foo() {}
}

class B implements I {
	public void foo() {}
}

class C extends A, B { // 不会编译
	public void bar() {
		super.foo();
	}
}

30. 如何在Java中演示try-catch示例?

以下示例代码显示了try-catch的示例:

try {
	FileInputStream fis = new FileInputStream("test.txt");
} catch(FileNotFoundException e) {
	e.printStackTrace();
}

从Java 7开始,您还可以在单个catch块中捕获多个异常,如以下示例所示。当所有catch块中的代码相同时,这很有用。

public static void foo(int x) throws IllegalArgumentException, NullPointerException {
	// 一些代码
}

public static void main(String[] args) {
	try {
		foo(10);
	} catch (IllegalArgumentException | NullPointerException e) {
		System.out.println(e.getMessage());
	}
}

31. 编写一个Java程序来展示NullPointerException

如果你在null上调用一个函数,它将抛出NullPointerException,如下例所示:

public static void main(String[] args) {
	printString(null, 3);
	
}

static void printString(String s, int count) {
	for (int i = 0; i < count; i++) {
		System.out.println(s.toUpperCase()); // Exception in thread "main" java.lang.NullPointerException
	}
}

你应该在早期验证时放置空检查,如下例所示:

static void printString(String s, int count) {
	if (s == null) return;
	for (int i = 0; i < count; i++) {
		System.out.println(s.toUpperCase());
	}
}

根据项目要求,你也可以抛出IllegalArgumentException

32. 如何在Java中创建记录?

记录是Java 16中添加的标准功能。记录使您能够使用最少的代码创建一个POJO类。记录自动生成hashCode()equals()、getter方法和toString()方法的代码。记录是final的,并隐式扩展了java.lang.Record类。以下示例代码展示了创建记录的一种方式:

import java.util.Map;
 
public record EmpRecord(int id, String name, long salary, Map<String, String> addresses) {
}

了解有关Java中的记录的更多信息。有关POJO的详细信息,请参阅维基百科上的普通旧Java对象。

33. 如何在Java中创建文本块?

Java 15添加了文本块功能。您可以使用文本块创建多行字符串。多行字符串必须写在一对三重双引号中,如以下示例所示:

String textBlock = """
		Hi
		Hello
		Yes""";

这与创建字符串相同,例如Hi\\nHello\\nYes

34. 在Java中显示switch表达式和多标签case语句的示例。

在Java 14中作为标准功能添加了switch表达式。以下示例显示了switch表达式以及多标签case语句:

int choice = 2;

int x = switch (choice) {
    case 1, 2, 3:
	    yield choice;
    default:
	    yield -1;
};

System.out.println("x = " + x); // x = 2

您还可以在switch表达式中使用lambda表达式。

String day = "TH";
String result = switch (day) {
    case "M", "W", "F" -> "MWF";
    case "T", "TH", "S" -> "TTS";

    default -> {
	    if (day.isEmpty())
		    yield "Please insert a valid day.";
	    else
		    yield "Looks like a Sunday.";
    }
};

System.out.println(result); // TTH

35. 如何从命令行编译和运行Java类?

这个示例是指以下Java文件:

public class Test {

public static void main(String args[]) {
		System.out.println("Hi");
	}

}

您可以使用以下命令在终端中进行编译:

  1. javac Test.java

要运行该类,请在终端中使用以下命令:

  1. java Test

对于最新版本,如果类文件不存在,java命令也将编译程序。如果类位于包中,例如com.example,那么它应该在文件夹com/example内。编译和运行的命令是:

  1. java com/example/Test.java

如果您的类需要一些额外的JAR文件进行编译和运行,您可以使用java -cp选项。例如:

  1. java -cp .:~/.m2/repository/log4j/log4j/1.2.17/log4j-1.2.17.jar com/example/Test.java

36. 如何在Java中创建枚举?

以下示例代码显示了如何创建一个基本的枚举:

public enum ThreadStates {
	START,
	RUNNING,
	WAITING,
	DEAD;
}

ThreadStates 是一个枚举,具有固定的常量字段 START, RUNNING, WAITING, 和 DEAD。所有枚举隐式地扩展了 java.lang.Enum 类,并实现了 SerializableComparable 接口。枚举也可以拥有方法。了解更多关于Java中的枚举

37. 如何在Java中使用 forEach() 方法?

forEach() 方法提供了一个快捷方式来对可迭代对象的所有元素执行操作。下面的示例代码展示了如何遍历列表元素并打印它们:

List<String> list = new ArrayList<>();

Iterator<String> it = list.iterator();

while (it.hasNext()) {
	System.out.println(it.next());
}

您可以使用 lambda 表达式来使用 forEach() 方法,以减少代码量,如下面的示例代码所示:

List<String> list = new ArrayList<>();

list.forEach(System.out::print);

38. 如何编写带有 defaultstatic 方法的接口?

Java 8 在接口中引入了默认方法和静态方法。这填补了接口与抽象类之间的差距。以下示例代码展示了一种编写带有defaultstatic方法的接口的方法:

public interface Interface1 {
	
	// 普通抽象方法
	void method1(String str);
	
	default void log(String str) {
		System.out.println("I1 logging::" + str);
	}
	
	static boolean isNull(String str) {
		System.out.println("Interface Null Check");

		return str == null ? true : "".equals(str) ? true : false;
	}

}

了解更多关于接口中defaultstatic方法的信息,请参阅Java 8 接口变化

39. 如何创建一个函数式接口?

具有正好一个抽象方法的接口称为函数式接口。函数式接口的主要好处是您可以使用 lambda 表达式来实例化它们,避免使用笨重的匿名类实现。@FunctionalInterface 注解表示一个函数式接口,如以下示例代码所示:

@FunctionalInterface
interface Foo {
	void test();
}

40. 展示在 Java 中使用 lambda 表达式的示例。

Runnable是函数式接口的一个很好的例子。您可以使用lambda表达式来创建一个Runnable,如下面的示例代码所示:

Runnable r1 = () -> System.out.println("My Runnable");

41.在Java中展示重载和重写的示例。

当一个类有两个或更多同名方法时,它们被称为重载方法。下面的示例代码展示了一个名为print的重载方法:

class Foo {
	void print(String s) {
		System.out.println(s);
	}

	void print(String s, int count) {
		while (count > 0) {
			System.out.println(s);
			count--;
		}
	}

}

当一个超类方法也在子类中实现时,它被称为重写。下面的示例代码展示了如何注释在两个类中都实现的printname()方法:

class Base {
	void printName() {
		System.out.println("Base Class");
	}
}

class Child extends Base {
	@Override
	void printName() {
		System.out.println("Child Class");
	}
}

了解更多关于Java中的重写和重载

42.-49.猜输出

通过猜测以下代码片段的输出来测试自己。


String s1 = "abc";
String s2 = "abc";

System.out.println("s1 == s2 is:" + s1 == s2);
Output
false

给定语句的输出是false,因为+运算符比==运算符的优先级更高。因此,给定表达式被求值为“s1 == s2 is:abc” == “abc”,这是false


String s3 = "JournalDev";
int start = 1;
char end = 5;

System.out.println(s3.substring(start, end));
Output
ourn

给定语句的输出是ourn。第一个字符自动转换为int。然后,由于第一个字符索引为0,它将从o开始打印,直到n。请注意,String substring方法创建一个从索引start开始,一直延伸到索引end - 1的子字符串。


HashSet shortSet = new HashSet();

	for (short i = 0; i < 100; i++) {
    shortSet.add(i);
    shortSet.remove(i - 1);
}

System.out.println(shortSet.size());
Output
100

shortSet的大小为100。Java中的自动装箱功能意味着具有原始类型short的表达式i会转换为Short对象。类似地,具有原始类型int的表达式i - 1会自动装箱为Integer对象。由于HashSet中没有Integer对象,因此不会删除任何内容,大小为100


try {
	if (flag) {
  		while (true) {
   		}
   	} else {
   		System.exit(1);
   	}
} finally {
   	System.out.println("In Finally");
}
Output

没有输出。如果标志为true,则此代码会导致无限循环,如果标志为false,则程序会退出。finally块将永远不会被执行。


String str = null;
String str1="abc";

System.out.println(str1.equals("abc") | str.equals(null));
Output
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "<local1>" is null

给定的打印语句会抛出一个java.lang.NullPointerException,因为OR逻辑运算符在返回结果之前会评估两个文字。由于strnull.equals()方法会抛出异常。始终建议使用短路逻辑运算符,例如||&&,它们会从左到右评估文字的值。在这种情况下,由于第一个文字将返回true,它会跳过第二个文字的评估。


String x = "abc";
String y = "abc";

x.concat(y);

System.out.print(x);
Output
abc

x.concat(y)创建一个新字符串,但未分配给x,因此x的值未更改。


public class MathTest {

 	public void main(String[] args) {  		
   		int x = 10 * 10 - 10;
   		
   		System.out.println(x);
   	}
   
}
Output
Error: Main method is not static in class MathTest, please define the main method as:
   public static void main(String[] args)

虽然这个问题似乎是关于数学运算符执行顺序的,但实际上是注意到主方法没有声明为static


public class Test {
   
  	public static void main(String[] args) {
   		try {
   			throw new IOException("Hello");
   		} catch(IOException | Exception e) {
   			System.out.println(e.getMessage());
   		}
   	}
}
Output
Test.java:5: error: cannot find symbol
   			throw new IOException("Hello");
   			          ^
  symbol:   class IOException
  location: class Test
Test.java:6: error: cannot find symbol
   		}catch(IOException | Exception e) {
   		       ^
  symbol:   class IOException
  location: class Test
2 errors

此代码导致编译时错误。异常IOException已被替代的Exception捕获。

50. 在以下代码片段中找出5个错误。

package com.digitalocean.programming-interviews;

public class String Programs {

	static void main(String[10] args) {
		String s = "abc"
		System.out.println(s);
	}
}
Answers
  1. 包名不能包含连字符。
  2. 类名不能包含空格。
  3. 主方法不是public,因此不会运行。
  4. 主方法参数不应指定大小。
  5. 字符串定义中缺少分号。

结论

这套包含了从初学者到专家级别的50个Java编程面试问题,旨在帮助您为面试做好准备。

推荐阅读:

Source:
https://www.digitalocean.com/community/tutorials/java-programming-interview-questions